abandon the use of ATEXIT(), we keep the fallback macros for backwards
[platform/upstream/glib.git] / gutils.c
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 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.
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  * Library General Public License for more details.
13  *
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.
18  */
19 #include <unistd.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <pwd.h>
25 #include <sys/types.h>
26 #include <sys/param.h>
27
28 /* implement Glib's inline functions
29  */
30 #define G_INLINE_FUNC extern
31 #define G_CAN_INLINE 1
32 #include "glib.h"
33
34 const guint glib_major_version = GLIB_MAJOR_VERSION;
35 const guint glib_minor_version = GLIB_MINOR_VERSION;
36 const guint glib_micro_version = GLIB_MICRO_VERSION;
37 const guint glib_interface_age = GLIB_INTERFACE_AGE;
38 const guint glib_binary_age = GLIB_BINARY_AGE;
39
40
41 void
42 g_atexit (GVoidFunc func)
43 {
44   gint result;
45   gchar *error = NULL;
46
47   /* keep this in sync with glib.h */
48
49 #ifdef  G_NATIVE_ATEXIT
50   result = ATEXIT (func);
51   if (result)
52     error = g_strerror (errno);
53 #elif defined (HAVE_ATEXIT)
54 #  ifdef NeXT /* @#%@! NeXTStep */
55   result = !atexit ((void (*)(void)) func);
56   if (result)
57     error = g_strerror (errno);
58 #  else
59   result = atexit ((void (*)(void)) func);
60   if (result)
61     error = g_strerror (errno);
62 #  endif /* NeXT */
63 #elif defined (HAVE_ON_EXIT)
64   result = on_exit ((void (*)(int, void *)) func, NULL);
65   if (result)
66     error = g_strerror (errno);
67 #else
68   result = 0;
69   error = "no implementation";
70 #endif /* G_NATIVE_ATEXIT */
71
72   if (error)
73     g_error ("Could not register atexit() function: %s", error);
74 }
75
76 gint
77 g_snprintf (gchar       *str,
78             gulong       n,
79             gchar const *fmt,
80             ...)
81 {
82 #ifdef  HAVE_VSNPRINTF
83   va_list args;
84   gint retval;
85   
86   va_start (args, fmt);
87   retval = vsnprintf (str, n, fmt, args);
88   va_end (args);
89   
90   return retval;
91 #else   /* !HAVE_VSNPRINTF */
92   gchar *printed;
93   va_list args;
94   
95   va_start (args, fmt);
96   printed = g_strdup_vprintf (fmt, args);
97   va_end (args);
98   
99   strncpy (str, printed, n);
100   str[n-1] = '\0';
101
102   g_free (printed);
103   
104   return strlen (str);
105 #endif  /* !HAVE_VSNPRINTF */
106 }
107
108 gint
109 g_vsnprintf (gchar       *str,
110              gulong       n,
111              gchar const *fmt,
112              va_list      args)
113 {
114 #ifdef  HAVE_VSNPRINTF
115   gint retval;
116   
117   retval = vsnprintf (str, n, fmt, args);
118   
119   return retval;
120 #else   /* !HAVE_VSNPRINTF */
121   gchar *printed;
122   
123   printed = g_strdup_vprintf (fmt, args);
124   strncpy (str, printed, n);
125   str[n-1] = '\0';
126
127   g_free (printed);
128   
129   return strlen (str);
130 #endif /* !HAVE_VSNPRINTF */
131 }
132
133 guint        
134 g_parse_debug_string  (const gchar *string, 
135                        GDebugKey   *keys, 
136                        guint        nkeys)
137 {
138   guint i;
139   guint result = 0;
140   
141   g_return_val_if_fail (string != NULL, 0);
142   
143   if (!g_strcasecmp (string, "all"))
144     {
145       for (i=0; i<nkeys; i++)
146         result |= keys[i].value;
147     }
148   else
149     {
150       gchar *str = g_strdup (string);
151       gchar *p = str;
152       gchar *q;
153       gboolean done = FALSE;
154       
155       while (*p && !done)
156         {
157           q = strchr (p, ':');
158           if (!q)
159             {
160               q = p + strlen(p);
161               done = TRUE;
162             }
163           
164           *q = 0;
165           
166           for (i=0; i<nkeys; i++)
167             if (!g_strcasecmp(keys[i].key, p))
168               result |= keys[i].value;
169           
170           p = q+1;
171         }
172       
173       g_free (str);
174     }
175   
176   return result;
177 }
178
179 gchar*
180 g_basename (const gchar    *file_name)
181 {
182   register gchar *base;
183   
184   g_return_val_if_fail (file_name != NULL, NULL);
185   
186   base = strrchr (file_name, '/');
187   if (base)
188     return base + 1;
189   
190   return (gchar*) file_name;
191 }
192
193 gchar*
194 g_dirname (const gchar     *file_name)
195 {
196   register gchar *base;
197   register guint len;
198   
199   g_return_val_if_fail (file_name != NULL, NULL);
200   
201   base = strrchr (file_name, '/');
202   if (!base)
203     return g_strdup (".");
204   while (base > file_name && *base == '/')
205     base--;
206   len = (guint) 1 + base - file_name;
207   
208   base = g_new (gchar, len + 1);
209   g_memmove (base, file_name, len);
210   base[len] = 0;
211   
212   return base;
213 }
214
215 #ifdef  MAXPATHLEN
216 #define G_PATH_LENGTH   (MAXPATHLEN + 1)
217 #elif   defined (PATH_MAX)
218 #define G_PATH_LENGTH   (PATH_MAX + 1)
219 #else   /* !MAXPATHLEN */
220 #define G_PATH_LENGTH   (2048 + 1)
221 #endif  /* !MAXPATHLEN && !PATH_MAX */
222
223 gchar*
224 g_get_current_dir (void)
225 {
226   gchar *buffer;
227   gchar *dir;
228
229   buffer = g_new (gchar, G_PATH_LENGTH);
230   *buffer = 0;
231   
232   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
233    * and, if that wasn't bad enough, hangs in doing so.
234    */
235 #if     defined (sun) && !defined (__SVR4)
236   dir = getwd (buffer);
237 #else   /* !sun */
238   dir = getcwd (buffer, G_PATH_LENGTH - 1);
239 #endif  /* !sun */
240   
241   if (!dir || !*buffer)
242     {
243       /* hm, should we g_error() out here?
244        * this can happen if e.g. "./" has mode \0000
245        */
246       buffer[0] = '/';
247       buffer[1] = 0;
248     }
249
250   dir = g_strdup (buffer);
251   g_free (buffer);
252   
253   return dir;
254 }
255
256 static  gchar   *g_tmp_dir = NULL;
257 static  gchar   *g_user_name = NULL;
258 static  gchar   *g_real_name = NULL;
259 static  gchar   *g_home_dir = NULL;
260
261 static void
262 g_get_any_init (void)
263 {
264   if (!g_tmp_dir)
265     {
266       struct passwd *pw;
267       
268       g_tmp_dir = g_strdup (getenv ("TMPDIR"));
269       if (!g_tmp_dir)
270         g_tmp_dir = g_strdup (getenv ("TMP"));
271       if (!g_tmp_dir)
272         g_tmp_dir = g_strdup (getenv ("TEMP"));
273       if (!g_tmp_dir)
274         g_tmp_dir = g_strdup ("/tmp");
275       
276       g_home_dir = g_strdup (getenv ("HOME"));
277       
278       setpwent ();
279       pw = getpwuid (getuid ());
280       endpwent ();
281       
282       if (pw)
283         {
284           g_user_name = g_strdup (pw->pw_name);
285           g_real_name = g_strdup (pw->pw_gecos);
286           if (!g_home_dir)
287             g_home_dir = g_strdup (pw->pw_dir);
288         }
289     }
290 }
291
292 gchar*
293 g_get_user_name (void)
294 {
295   if (!g_tmp_dir)
296     g_get_any_init ();
297   
298   return g_user_name;
299 }
300
301 gchar*
302 g_get_real_name (void)
303 {
304   if (!g_tmp_dir)
305     g_get_any_init ();
306   
307   return g_real_name;
308 }
309
310 gchar*
311 g_get_home_dir (void)
312 {
313   if (!g_tmp_dir)
314     g_get_any_init ();
315   
316   return g_home_dir;
317 }
318
319 gchar*
320 g_get_tmp_dir (void)
321 {
322   if (!g_tmp_dir)
323     g_get_any_init ();
324   
325   return g_tmp_dir;
326 }
327
328 static gchar *g_prgname = NULL;
329
330 gchar*
331 g_get_prgname (void)
332 {
333   return g_prgname;
334 }
335
336 void
337 g_set_prgname (const gchar *prgname)
338 {
339   gchar *c = g_prgname;
340   
341   g_prgname = g_strdup (prgname);
342   g_free (c);
343 }
344
345 guint
346 g_direct_hash(gconstpointer v)
347 {
348   return GPOINTER_TO_UINT (v);
349 }
350
351 gint
352 g_direct_equal(gconstpointer v, gconstpointer v2)
353 {
354   return GPOINTER_TO_UINT (v) == GPOINTER_TO_UINT (v2);
355 }
356
357 gint
358 g_int_equal (gconstpointer v, gconstpointer v2)
359 {
360   return *((const gint*) v) == *((const gint*) v2);
361 }
362
363 guint
364 g_int_hash (gconstpointer v)
365 {
366   return *(const gint*) v;
367 }