gutils.c 86.6 KB
Newer Older
Owen Taylor's avatar
Owen Taylor committed
1
/* GLIB - Library of useful routines for C programming
2
 * Copyright (C) 1995-1998  Peter Mattis, Spencer Kimball and Josh MacDonald
Owen Taylor's avatar
Owen Taylor committed
3
4
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Owen Taylor's avatar
Owen Taylor committed
6
7
8
9
10
11
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
Owen Taylor's avatar
Owen Taylor committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Owen Taylor's avatar
Owen Taylor committed
15
16
17
18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
19

20
/*
21
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22
23
24
25
26
 * file for a list of people on the GLib Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
 */

27
28
29
30
/* 
 * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
 */

31
#include "config.h"
32

33
#ifdef HAVE_UNISTD_H
34
#include <unistd.h>
35
#endif
Owen Taylor's avatar
Owen Taylor committed
36
37
#include <stdarg.h>
#include <stdlib.h>
38
#include <stdio.h>
39
#include <locale.h>
Owen Taylor's avatar
Owen Taylor committed
40
#include <string.h>
41
#include <ctype.h>		/* For tolower() */
Manish Singh's avatar
Manish Singh committed
42
#include <errno.h>
43
44
#include <sys/types.h>
#include <sys/stat.h>
45
#ifdef HAVE_PWD_H
46
#include <pwd.h>
47
#endif
48
#include <sys/types.h>
49
#ifdef HAVE_SYS_PARAM_H
50
#include <sys/param.h>
51
#endif
52
#ifdef HAVE_CRT_EXTERNS_H 
53
#include <crt_externs.h> /* for _NSGetEnviron */
54
#endif
55

Owen Taylor's avatar
Owen Taylor committed
56
/* implement gutils's inline functions
57
 */
58
59
#define	G_IMPLEMENT_INLINES 1
#define	__G_UTILS_C__
Owen Taylor's avatar
Owen Taylor committed
60
#include "glib.h"
61
#include "gprintfint.h"
62
#include "gthreadprivate.h"
Alexander Larsson's avatar
Alexander Larsson committed
63
#include "glibintl.h"
64
#include "galias.h"
Owen Taylor's avatar
Owen Taylor committed
65

66
#ifdef	MAXPATHLEN
67
#define	G_PATH_LENGTH	MAXPATHLEN
68
#elif	defined (PATH_MAX)
69
70
71
72
73
74
#define	G_PATH_LENGTH	PATH_MAX
#elif   defined (_PC_PATH_MAX)
#define	G_PATH_LENGTH	sysconf(_PC_PATH_MAX)
#else	
#define G_PATH_LENGTH   2048
#endif
75

76
#ifdef G_PLATFORM_WIN32
77
#  define STRICT		/* Strict typing, please */
78
#  include <windows.h>
79
#  undef STRICT
80
81
82
83
#  ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
#    define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 2
#    define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
#  endif
84
#  include <lmcons.h>		/* For UNLEN */
85
86
87
#endif /* G_PLATFORM_WIN32 */

#ifdef G_OS_WIN32
88
#  include <direct.h>
89
#  include <shlobj.h>
90
   /* older SDK (e.g. msvc 5.0) does not have these*/
91
92
93
94
95
96
#  ifndef CSIDL_MYMUSIC
#    define CSIDL_MYMUSIC 13
#  endif
#  ifndef CSIDL_MYVIDEO
#    define CSIDL_MYVIDEO 14
#  endif
97
98
99
100
101
102
#  ifndef CSIDL_INTERNET_CACHE
#    define CSIDL_INTERNET_CACHE 32
#  endif
#  ifndef CSIDL_COMMON_APPDATA
#    define CSIDL_COMMON_APPDATA 35
#  endif
103
104
105
#  ifndef CSIDL_MYPICTURES
#    define CSIDL_MYPICTURES 0x27
#  endif
106
107
108
109
110
111
#  ifndef CSIDL_COMMON_DOCUMENTS
#    define CSIDL_COMMON_DOCUMENTS 46
#  endif
#  ifndef CSIDL_PROFILE
#    define CSIDL_PROFILE 40
#  endif
112
#  include <process.h>
113
#endif
114

115
116
117
118
#ifdef HAVE_CARBON
#include <CoreServices/CoreServices.h>
#endif

119
120
121
122
#ifdef HAVE_CODESET
#include <langinfo.h>
#endif

Owen Taylor's avatar
Owen Taylor committed
123
124
125
const guint glib_major_version = GLIB_MAJOR_VERSION;
const guint glib_minor_version = GLIB_MINOR_VERSION;
const guint glib_micro_version = GLIB_MICRO_VERSION;
126
127
const guint glib_interface_age = GLIB_INTERFACE_AGE;
const guint glib_binary_age = GLIB_BINARY_AGE;
Owen Taylor's avatar
Owen Taylor committed
128

129
130
#ifdef G_PLATFORM_WIN32

131
132
static HMODULE glib_dll = NULL;

133
134
#ifdef DLL_EXPORT

135
136
137
138
139
140
141
142
143
144
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
	 DWORD     fdwReason,
	 LPVOID    lpvReserved)
{
  if (fdwReason == DLL_PROCESS_ATTACH)
      glib_dll = hinstDLL;

  return TRUE;
}
145

146
147
#endif

Tor Lillqvist's avatar
Tor Lillqvist committed
148
gchar *
149
_glib_get_dll_directory (void)
Tor Lillqvist's avatar
Tor Lillqvist committed
150
{
151
152
153
154
  gchar *retval;
  gchar *p;
  wchar_t wc_fn[MAX_PATH];

155
#ifdef DLL_EXPORT
Tor Lillqvist's avatar
Tor Lillqvist committed
156
157
  if (glib_dll == NULL)
    return NULL;
158
#endif
159
160
161
162
163
164
165
166
167

  /* This code is different from that in
   * g_win32_get_package_installation_directory_of_module() in that
   * here we return the actual folder where the GLib DLL is. We don't
   * do the check for it being in a "bin" or "lib" subfolder and then
   * returning the parent of that.
   *
   * In a statically built GLib, glib_dll will be NULL and we will
   * thus look up the application's .exe file's location.
168
   */
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  if (!GetModuleFileNameW (glib_dll, wc_fn, MAX_PATH))
    return NULL;

  retval = g_utf16_to_utf8 (wc_fn, -1, NULL, NULL, NULL);

  p = strrchr (retval, G_DIR_SEPARATOR);
  if (p == NULL)
    {
      /* Wtf? */
      return NULL;
    }
  *p = '\0';

  return retval;
Tor Lillqvist's avatar
Tor Lillqvist committed
183
184
}

185
186
#endif

187
188
189
/**
 * glib_check_version:
 * @required_major: the required major version.
190
191
 * @required_minor: the required minor version.
 * @required_micro: the required micro version.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
 *
 * Checks that the GLib library in use is compatible with the
 * given version. Generally you would pass in the constants
 * #GLIB_MAJOR_VERSION, #GLIB_MINOR_VERSION, #GLIB_MICRO_VERSION
 * as the three arguments to this function; that produces
 * a check that the library in use is compatible with
 * the version of GLib the application or module was compiled
 * against.
 *
 * Compatibility is defined by two things: first the version
 * of the running library is newer than the version
 * @required_major.required_minor.@required_micro. Second
 * the running library must be binary compatible with the
 * version @required_major.required_minor.@required_micro
 * (same major version.)
 *
 * Return value: %NULL if the GLib library is compatible with the
 *   given version, or a string describing the version mismatch.
 *   The returned string is owned by GLib and must not be modified
 *   or freed.
 *
 * Since: 2.6
 **/
const gchar *
glib_check_version (guint required_major,
                    guint required_minor,
                    guint required_micro)
{
  gint glib_effective_micro = 100 * GLIB_MINOR_VERSION + GLIB_MICRO_VERSION;
  gint required_effective_micro = 100 * required_minor + required_micro;

  if (required_major > GLIB_MAJOR_VERSION)
    return "GLib version too old (major mismatch)";
  if (required_major < GLIB_MAJOR_VERSION)
    return "GLib version too new (major mismatch)";
  if (required_effective_micro < glib_effective_micro - GLIB_BINARY_AGE)
    return "GLib version too new (micro mismatch)";
  if (required_effective_micro > glib_effective_micro)
    return "GLib version too old (micro mismatch)";
  return NULL;
}

234
#if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
Matthias Clasen's avatar
Matthias Clasen committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/**
 * g_memmove: 
 * @dest: the destination address to copy the bytes to.
 * @src: the source address to copy the bytes from.
 * @len: the number of bytes to copy.
 *
 * Copies a block of memory @len bytes long, from @src to @dest.
 * The source and destination areas may overlap.
 *
 * In order to use this function, you must include 
 * <filename>string.h</filename> yourself, because this macro will 
 * typically simply resolve to memmove() and GLib does not include 
 * <filename>string.h</filename> for you.
 */
249
void 
Matthias Clasen's avatar
Matthias Clasen committed
250
251
252
g_memmove (gpointer      dest, 
	   gconstpointer src, 
	   gulong        len)
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
{
  gchar* destptr = dest;
  const gchar* srcptr = src;
  if (src + len < dest || dest + len < src)
    {
      bcopy (src, dest, len);
      return;
    }
  else if (dest <= src)
    {
      while (len--)
	*(destptr++) = *(srcptr++);
    }
  else
    {
      destptr += len;
      srcptr += len;
      while (len--)
	*(--destptr) = *(--srcptr);
    }
}
#endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */

276
277
278
279
#ifdef G_OS_WIN32
#undef g_atexit
#endif

Matthias Clasen's avatar
Matthias Clasen committed
280
281
282
283
284
/**
 * g_atexit:
 * @func: the function to call on normal program termination.
 * 
 * Specifies a function to be called at normal program termination.
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
 *
 * Since GLib 2.8.2, on Windows g_atexit() actually is a preprocessor
 * macro that maps to a call to the atexit() function in the C
 * library. This means that in case the code that calls g_atexit(),
 * i.e. atexit(), is in a DLL, the function will be called when the
 * DLL is detached from the program. This typically makes more sense
 * than that the function is called when the GLib DLL is detached,
 * which happened earlier when g_atexit() was a function in the GLib
 * DLL.
 *
 * The behaviour of atexit() in the context of dynamically loaded
 * modules is not formally specified and varies wildly.
 *
 * On POSIX systems, calling g_atexit() (or atexit()) in a dynamically
 * loaded module which is unloaded before the program terminates might
 * well cause a crash at program exit.
 *
 * Some POSIX systems implement atexit() like Windows, and have each
 * dynamically loaded module maintain an own atexit chain that is
 * called when the module is unloaded.
 *
 * On other POSIX systems, before a dynamically loaded module is
 * unloaded, the registered atexit functions (if any) residing in that
 * module are called, regardless where the code that registered them
 * resided. This is presumably the most robust approach.
 *
 * As can be seen from the above, for portability it's best to avoid
 * calling g_atexit() (or atexit()) except in the main executable of a
 * program.
Matthias Clasen's avatar
Matthias Clasen committed
314
 */
315
316
317
318
void
g_atexit (GVoidFunc func)
{
  gint result;
Havoc Pennington's avatar
Havoc Pennington committed
319
  const gchar *error = NULL;
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

  /* keep this in sync with glib.h */

#ifdef	G_NATIVE_ATEXIT
  result = ATEXIT (func);
  if (result)
    error = g_strerror (errno);
#elif defined (HAVE_ATEXIT)
#  ifdef NeXT /* @#%@! NeXTStep */
  result = !atexit ((void (*)(void)) func);
  if (result)
    error = g_strerror (errno);
#  else
  result = atexit ((void (*)(void)) func);
  if (result)
    error = g_strerror (errno);
#  endif /* NeXT */
#elif defined (HAVE_ON_EXIT)
  result = on_exit ((void (*)(int, void *)) func, NULL);
  if (result)
    error = g_strerror (errno);
#else
  result = 0;
  error = "no implementation";
#endif /* G_NATIVE_ATEXIT */

  if (error)
    g_error ("Could not register atexit() function: %s", error);
}

Havoc Pennington's avatar
Havoc Pennington committed
350
351
352
353
354
/* Based on execvp() from GNU Libc.
 * Some of this code is cut-and-pasted into gspawn.c
 */

static gchar*
Matthias Clasen's avatar
Matthias Clasen committed
355
356
my_strchrnul (const gchar *str, 
	      gchar        c)
Havoc Pennington's avatar
Havoc Pennington committed
357
358
359
360
361
362
363
364
{
  gchar *p = (gchar*)str;
  while (*p && (*p != c))
    ++p;

  return p;
}

365
366
#ifdef G_OS_WIN32

367
static gchar *inner_find_program_in_path (const gchar *program);
368
369
370
371
372
373

gchar*
g_find_program_in_path (const gchar *program)
{
  const gchar *last_dot = strrchr (program, '.');

374
375
376
  if (last_dot == NULL ||
      strchr (last_dot, '\\') != NULL ||
      strchr (last_dot, '/') != NULL)
377
378
    {
      const gint program_length = strlen (program);
379
380
381
382
383
      gchar *pathext = g_build_path (";",
				     ".exe;.cmd;.bat;.com",
				     g_getenv ("PATHEXT"),
				     NULL);
      gchar *p;
384
385
386
387
388
389
      gchar *decorated_program;
      gchar *retval;

      p = pathext;
      do
	{
390
	  gchar *q = my_strchrnul (p, ';');
391

392
	  decorated_program = g_malloc (program_length + (q-p) + 1);
393
	  memcpy (decorated_program, program, program_length);
394
395
	  memcpy (decorated_program+program_length, p, q-p);
	  decorated_program [program_length + (q-p)] = '\0';
396
397
398
399
400
	  
	  retval = inner_find_program_in_path (decorated_program);
	  g_free (decorated_program);

	  if (retval != NULL)
401
402
403
404
405
	    {
	      g_free (pathext);
	      return retval;
	    }
	  p = q;
406
	} while (*p++ != '\0');
407
      g_free (pathext);
408
409
410
411
412
413
414
415
      return NULL;
    }
  else
    return inner_find_program_in_path (program);
}

#endif

Havoc Pennington's avatar
Havoc Pennington committed
416
417
/**
 * g_find_program_in_path:
418
 * @program: a program name in the GLib file name encoding
Havoc Pennington's avatar
Havoc Pennington committed
419
 * 
Havoc Pennington's avatar
Added    
Havoc Pennington committed
420
 * Locates the first executable named @program in the user's path, in the
Havoc Pennington's avatar
Havoc Pennington committed
421
 * same way that execvp() would locate it. Returns an allocated string
422
 * with the absolute path name, or %NULL if the program is not found in
Havoc Pennington's avatar
Added    
Havoc Pennington committed
423
 * the path. If @program is already an absolute path, returns a copy of
424
425
 * @program if @program exists and is executable, and %NULL otherwise.
 *  
426
427
 * On Windows, if @program does not have a file type suffix, tries
 * with the suffixes .exe, .cmd, .bat and .com, and the suffixes in
428
429
430
 * the <envar>PATHEXT</envar> environment variable. 
 * 
 * On Windows, it looks for the file in the same way as CreateProcess() 
431
 * would. This means first in the directory where the executing
432
433
 * program was loaded from, then in the current directory, then in the
 * Windows 32-bit system directory, then in the Windows directory, and
434
435
436
 * finally in the directories in the <envar>PATH</envar> environment 
 * variable. If the program is found, the return value contains the 
 * full name including the type suffix.
437
 *
438
 * Return value: absolute path, or %NULL
Havoc Pennington's avatar
Havoc Pennington committed
439
 **/
440
#ifdef G_OS_WIN32
441
442
443
static gchar *
inner_find_program_in_path (const gchar *program)
#else
Havoc Pennington's avatar
Havoc Pennington committed
444
gchar*
Havoc Pennington's avatar
Added    
Havoc Pennington committed
445
g_find_program_in_path (const gchar *program)
446
#endif
Havoc Pennington's avatar
Havoc Pennington committed
447
{
Havoc Pennington's avatar
Havoc Pennington committed
448
449
  const gchar *path, *p;
  gchar *name, *freeme;
450
#ifdef G_OS_WIN32
451
452
453
  const gchar *path_copy;
  gchar *filename = NULL, *appdir = NULL;
  gchar *sysdir = NULL, *windir = NULL;
454
455
456
  int n;
  wchar_t wfilename[MAXPATHLEN], wsysdir[MAXPATHLEN],
    wwindir[MAXPATHLEN];
457
#endif
458
459
  gsize len;
  gsize pathlen;
Havoc Pennington's avatar
Havoc Pennington committed
460

Havoc Pennington's avatar
Added    
Havoc Pennington committed
461
  g_return_val_if_fail (program != NULL, NULL);
Havoc Pennington's avatar
Havoc Pennington committed
462

463
464
465
466
  /* If it is an absolute path, or a relative path including subdirectories,
   * don't look in PATH.
   */
  if (g_path_is_absolute (program)
Tor Lillqvist's avatar
Tor Lillqvist committed
467
468
469
470
471
      || strchr (program, G_DIR_SEPARATOR) != NULL
#ifdef G_OS_WIN32
      || strchr (program, '/') != NULL
#endif
      )
Havoc Pennington's avatar
Havoc Pennington committed
472
    {
473
474
      if (g_file_test (program, G_FILE_TEST_IS_EXECUTABLE) &&
	  !g_file_test (program, G_FILE_TEST_IS_DIR))
Havoc Pennington's avatar
Added    
Havoc Pennington committed
475
        return g_strdup (program);
Havoc Pennington's avatar
Havoc Pennington committed
476
477
478
479
480
      else
        return NULL;
    }
  
  path = g_getenv ("PATH");
481
#if defined(G_OS_UNIX) || defined(G_OS_BEOS)
Havoc Pennington's avatar
Havoc Pennington committed
482
483
484
  if (path == NULL)
    {
      /* There is no `PATH' in the environment.  The default
Havoc Pennington's avatar
Added    
Havoc Pennington committed
485
       * search path in GNU libc is the current directory followed by
Havoc Pennington's avatar
Havoc Pennington committed
486
487
488
489
490
491
492
493
494
495
       * the path `confstr' returns for `_CS_PATH'.
       */
      
      /* In GLib we put . last, for security, and don't use the
       * unportable confstr(); UNIX98 does not actually specify
       * what to search if PATH is unset. POSIX may, dunno.
       */
      
      path = "/bin:/usr/bin:.";
    }
496
#else
497
498
499
500
501
502
503
504
505
506
507
  n = GetModuleFileNameW (NULL, wfilename, MAXPATHLEN);
  if (n > 0 && n < MAXPATHLEN)
    filename = g_utf16_to_utf8 (wfilename, -1, NULL, NULL, NULL);
  
  n = GetSystemDirectoryW (wsysdir, MAXPATHLEN);
  if (n > 0 && n < MAXPATHLEN)
    sysdir = g_utf16_to_utf8 (wsysdir, -1, NULL, NULL, NULL);
  
  n = GetWindowsDirectoryW (wwindir, MAXPATHLEN);
  if (n > 0 && n < MAXPATHLEN)
    windir = g_utf16_to_utf8 (wwindir, -1, NULL, NULL, NULL);
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  
  if (filename)
    {
      appdir = g_path_get_dirname (filename);
      g_free (filename);
    }
  
  path = g_strdup (path);

  if (windir)
    {
      const gchar *tem = path;
      path = g_strconcat (windir, ";", path, NULL);
      g_free ((gchar *) tem);
      g_free (windir);
    }
  
  if (sysdir)
    {
      const gchar *tem = path;
      path = g_strconcat (sysdir, ";", path, NULL);
      g_free ((gchar *) tem);
      g_free (sysdir);
    }
  
533
  {
534
535
536
    const gchar *tem = path;
    path = g_strconcat (".;", path, NULL);
    g_free ((gchar *) tem);
537
  }
538
539
540
541
542
543
544
545
546
547
  
  if (appdir)
    {
      const gchar *tem = path;
      path = g_strconcat (appdir, ";", path, NULL);
      g_free ((gchar *) tem);
      g_free (appdir);
    }

  path_copy = path;
548
#endif
Havoc Pennington's avatar
Havoc Pennington committed
549
  
Havoc Pennington's avatar
Added    
Havoc Pennington committed
550
  len = strlen (program) + 1;
Havoc Pennington's avatar
Havoc Pennington committed
551
552
553
554
  pathlen = strlen (path);
  freeme = name = g_malloc (pathlen + len + 1);
  
  /* Copy the file name at the top, including '\0'  */
Havoc Pennington's avatar
Added    
Havoc Pennington committed
555
  memcpy (name + pathlen + 1, program, len);
Havoc Pennington's avatar
Havoc Pennington committed
556
557
  name = name + pathlen;
  /* And add the slash before the filename  */
558
  *name = G_DIR_SEPARATOR;
Havoc Pennington's avatar
Havoc Pennington committed
559
560
561
562
563
564
565
  
  p = path;
  do
    {
      char *startp;

      path = p;
566
      p = my_strchrnul (path, G_SEARCHPATH_SEPARATOR);
Havoc Pennington's avatar
Havoc Pennington committed
567
568
569
570
571
572
573
574
575

      if (p == path)
        /* Two adjacent colons, or a colon at the beginning or the end
         * of `PATH' means to search the current directory.
         */
        startp = name + 1;
      else
        startp = memcpy (name - (p - path), path, p - path);

576
577
      if (g_file_test (startp, G_FILE_TEST_IS_EXECUTABLE) &&
	  !g_file_test (startp, G_FILE_TEST_IS_DIR))
Havoc Pennington's avatar
Havoc Pennington committed
578
579
580
581
        {
          gchar *ret;
          ret = g_strdup (startp);
          g_free (freeme);
582
#ifdef G_OS_WIN32
583
	  g_free ((gchar *) path_copy);
584
#endif
Havoc Pennington's avatar
Havoc Pennington committed
585
586
587
588
589
590
          return ret;
        }
    }
  while (*p++ != '\0');
  
  g_free (freeme);
591
#ifdef G_OS_WIN32
592
  g_free ((gchar *) path_copy);
593
#endif
Havoc Pennington's avatar
Havoc Pennington committed
594
595
596
597

  return NULL;
}

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
static gboolean
debug_key_matches (const gchar *key,
		   const gchar *token,
		   guint        length)
{
  for (; length; length--, key++, token++)
    {
      char k = (*key   == '_') ? '-' : tolower (*key  );
      char t = (*token == '_') ? '-' : tolower (*token);

      if (k != t)
        return FALSE;
    }

  return *key == '\0';
}

Matthias Clasen's avatar
Matthias Clasen committed
615
616
/**
 * g_parse_debug_string:
617
 * @string: a list of debug options separated by colons, spaces, or
618
 * commas; or the string "all" to set all flags, or %NULL.
Matthias Clasen's avatar
Matthias Clasen committed
619
620
621
622
 * @keys: pointer to an array of #GDebugKey which associate 
 *     strings with bit flags.
 * @nkeys: the number of #GDebugKey<!-- -->s in the array.
 *
623
624
 * Parses a string containing debugging options
 * into a %guint containing bit flags. This is used 
Matthias Clasen's avatar
Matthias Clasen committed
625
626
627
628
629
 * within GDK and GTK+ to parse the debug options passed on the
 * command line or through environment variables.
 *
 * Returns: the combined set of bit flags.
 */
630
guint	     
631
632
633
g_parse_debug_string  (const gchar     *string, 
		       const GDebugKey *keys, 
		       guint	        nkeys)
Owen Taylor's avatar
Owen Taylor committed
634
635
636
{
  guint i;
  guint result = 0;
637
  
638
639
  if (string == NULL)
    return 0;
640
641
642
643
644

  /* this function is used by gmem.c/gslice.c initialization code,
   * so introducing malloc dependencies here would require adaptions
   * of those code portions.
   */
645
  
Owen Taylor's avatar
Owen Taylor committed
646
  if (!g_ascii_strcasecmp (string, "all"))
Owen Taylor's avatar
Owen Taylor committed
647
648
649
650
651
652
    {
      for (i=0; i<nkeys; i++)
	result |= keys[i].value;
    }
  else
    {
653
654
      const gchar *p = string;
      const gchar *q;
655
      
656
      while (*p)
Owen Taylor's avatar
Owen Taylor committed
657
	{
658
	  q = strpbrk (p, ":;, \t");
Owen Taylor's avatar
Owen Taylor committed
659
	  if (!q)
660
	    q = p + strlen(p);
661
	  
662
	  for (i = 0; i < nkeys; i++)
663
	    if (debug_key_matches (keys[i].key, p, q - p))
Owen Taylor's avatar
Owen Taylor committed
664
	      result |= keys[i].value;
665
	  
666
	  p = q;
667
	  if (*p)
668
	    p++;
Owen Taylor's avatar
Owen Taylor committed
669
670
	}
    }
671
  
Owen Taylor's avatar
Owen Taylor committed
672
673
674
  return result;
}

675
676
677
678
679
680
681
682
683
/**
 * g_basename:
 * @file_name: the name of the file.
 * 
 * Gets the name of the file without any leading directory components.  
 * It returns a pointer into the given file name string.
 * 
 * Return value: the name of the file without any leading directory components.
 *
684
 * Deprecated:2.2: Use g_path_get_basename() instead, but notice that
685
686
 * g_path_get_basename() allocates new memory for the returned string, unlike
 * this function which returns a pointer into the argument.
687
 **/
Havoc Pennington's avatar
Havoc Pennington committed
688
G_CONST_RETURN gchar*
689
690
691
692
693
694
g_basename (const gchar	   *file_name)
{
  register gchar *base;
  
  g_return_val_if_fail (file_name != NULL, NULL);
  
695
  base = strrchr (file_name, G_DIR_SEPARATOR);
Tor Lillqvist's avatar
Tor Lillqvist committed
696
697
698
699
700
701
702
703
704

#ifdef G_OS_WIN32
  {
    gchar *q = strrchr (file_name, '/');
    if (base == NULL || (q != NULL && q > base))
	base = q;
  }
#endif

705
706
  if (base)
    return base + 1;
707

708
#ifdef G_OS_WIN32
Owen Taylor's avatar
Owen Taylor committed
709
  if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
710
    return (gchar*) file_name + 2;
711
#endif /* G_OS_WIN32 */
712
713
714
715
  
  return (gchar*) file_name;
}

716
717
718
719
720
721
722
723
724
725
726
727
728
/**
 * g_path_get_basename:
 * @file_name: the name of the file.
 *
 * Gets the last component of the filename. If @file_name ends with a 
 * directory separator it gets the component before the last slash. If 
 * @file_name consists only of directory separators (and on Windows, 
 * possibly a drive letter), a single separator is returned. If
 * @file_name is empty, it gets ".".
 *
 * Return value: a newly allocated string containing the last component of 
 *   the filename.
 */
729
730
731
gchar*
g_path_get_basename (const gchar   *file_name)
{
732
733
734
  register gssize base;             
  register gssize last_nonslash;    
  gsize len;    
735
736
737
  gchar *retval;
 
  g_return_val_if_fail (file_name != NULL, NULL);
738

739
740
741
  if (file_name[0] == '\0')
    /* empty string */
    return g_strdup (".");
742
  
743
744
  last_nonslash = strlen (file_name) - 1;

Tor Lillqvist's avatar
Tor Lillqvist committed
745
  while (last_nonslash >= 0 && G_IS_DIR_SEPARATOR (file_name [last_nonslash]))
746
747
748
749
750
751
752
    last_nonslash--;

  if (last_nonslash == -1)
    /* string only containing slashes */
    return g_strdup (G_DIR_SEPARATOR_S);

#ifdef G_OS_WIN32
Owen Taylor's avatar
Owen Taylor committed
753
  if (last_nonslash == 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
754
755
756
757
758
759
    /* string only containing slashes and a drive */
    return g_strdup (G_DIR_SEPARATOR_S);
#endif /* G_OS_WIN32 */

  base = last_nonslash;

Tor Lillqvist's avatar
Tor Lillqvist committed
760
  while (base >=0 && !G_IS_DIR_SEPARATOR (file_name [base]))
761
762
763
    base--;

#ifdef G_OS_WIN32
Owen Taylor's avatar
Owen Taylor committed
764
  if (base == -1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
765
766
767
768
769
770
771
772
773
774
    base = 1;
#endif /* G_OS_WIN32 */

  len = last_nonslash - base;
  retval = g_malloc (len + 1);
  memcpy (retval, file_name + base + 1, len);
  retval [len] = '\0';
  return retval;
}

Matthias Clasen's avatar
Matthias Clasen committed
775
776
777
778
779
780
781
782
783
784
/**
 * g_path_is_absolute:
 * @file_name: a file name.
 *
 * Returns %TRUE if the given @file_name is an absolute file name,
 * i.e. it contains a full path from the root directory such as "/usr/local"
 * on UNIX or "C:\windows" on Windows systems.
 *
 * Returns: %TRUE if @file_name is an absolute path. 
 */
785
786
787
788
789
gboolean
g_path_is_absolute (const gchar *file_name)
{
  g_return_val_if_fail (file_name != NULL, FALSE);
  
Tor Lillqvist's avatar
Tor Lillqvist committed
790
  if (G_IS_DIR_SEPARATOR (file_name[0]))
791
792
    return TRUE;

793
#ifdef G_OS_WIN32
794
  /* Recognize drive letter on native Windows */
Matthias Clasen's avatar
Matthias Clasen committed
795
796
  if (g_ascii_isalpha (file_name[0]) && 
      file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
797
    return TRUE;
798
#endif /* G_OS_WIN32 */
799
800
801
802

  return FALSE;
}

Matthias Clasen's avatar
Matthias Clasen committed
803
804
805
806
807
808
809
810
811
812
/**
 * g_path_skip_root:
 * @file_name: a file name.
 *
 * Returns a pointer into @file_name after the root component, i.e. after
 * the "/" in UNIX or "C:\" under Windows. If @file_name is not an absolute
 * path it returns %NULL.
 *
 * Returns: a pointer into @file_name after the root component.
 */
Havoc Pennington's avatar
Havoc Pennington committed
813
814
G_CONST_RETURN gchar*
g_path_skip_root (const gchar *file_name)
815
816
817
{
  g_return_val_if_fail (file_name != NULL, NULL);
  
818
#ifdef G_PLATFORM_WIN32
Tor Lillqvist's avatar
Tor Lillqvist committed
819
820
821
  /* Skip \\server\share or //server/share */
  if (G_IS_DIR_SEPARATOR (file_name[0]) &&
      G_IS_DIR_SEPARATOR (file_name[1]) &&
822
823
      file_name[2] &&
      !G_IS_DIR_SEPARATOR (file_name[2]))
824
    {
825
      gchar *p;
826

Tor Lillqvist's avatar
Tor Lillqvist committed
827
828
829
830
831
832
833
834
835
836
      p = strchr (file_name + 2, G_DIR_SEPARATOR);
#ifdef G_OS_WIN32
      {
	gchar *q = strchr (file_name + 2, '/');
	if (p == NULL || (q != NULL && q < p))
	  p = q;
      }
#endif
      if (p &&
	  p > file_name + 2 &&
837
838
839
840
	  p[1])
	{
	  file_name = p + 1;

Tor Lillqvist's avatar
Tor Lillqvist committed
841
	  while (file_name[0] && !G_IS_DIR_SEPARATOR (file_name[0]))
842
843
844
	    file_name++;

	  /* Possibly skip a backslash after the share name */
Tor Lillqvist's avatar
Tor Lillqvist committed
845
	  if (G_IS_DIR_SEPARATOR (file_name[0]))
846
847
	    file_name++;

Havoc Pennington's avatar
Havoc Pennington committed
848
	  return (gchar *)file_name;
849
850
	}
    }
851
852
853
#endif
  
  /* Skip initial slashes */
Tor Lillqvist's avatar
Tor Lillqvist committed
854
  if (G_IS_DIR_SEPARATOR (file_name[0]))
855
    {
Tor Lillqvist's avatar
Tor Lillqvist committed
856
      while (G_IS_DIR_SEPARATOR (file_name[0]))
857
	file_name++;
Havoc Pennington's avatar
Havoc Pennington committed
858
      return (gchar *)file_name;
859
    }
860

861
#ifdef G_OS_WIN32
862
  /* Skip X:\ */
Tor Lillqvist's avatar
Tor Lillqvist committed
863
  if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':' && G_IS_DIR_SEPARATOR (file_name[2]))
Havoc Pennington's avatar
Havoc Pennington committed
864
    return (gchar *)file_name + 3;
865
866
867
868
869
#endif

  return NULL;
}

Matthias Clasen's avatar
Matthias Clasen committed
870
871
872
873
874
875
876
877
878
879
/**
 * g_path_get_dirname:
 * @file_name: the name of the file.
 *
 * Gets the directory components of a file name.  If the file name has no
 * directory components "." is returned.  The returned string should be
 * freed when no longer needed.
 * 
 * Returns: the directory components of the file.
 */
880
gchar*
881
g_path_get_dirname (const gchar	   *file_name)
882
883
{
  register gchar *base;
884
  register gsize len;    
885
886
887
  
  g_return_val_if_fail (file_name != NULL, NULL);
  
888
  base = strrchr (file_name, G_DIR_SEPARATOR);
Tor Lillqvist's avatar
Tor Lillqvist committed
889
890
891
892
893
894
895
#ifdef G_OS_WIN32
  {
    gchar *q = strrchr (file_name, '/');
    if (base == NULL || (q != NULL && q > base))
	base = q;
  }
#endif
896
  if (!base)
897
898
899
900
901
902
903
904
905
906
907
908
909
910
    {
#ifdef G_OS_WIN32
      if (g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
	{
	  gchar drive_colon_dot[4];

	  drive_colon_dot[0] = file_name[0];
	  drive_colon_dot[1] = ':';
	  drive_colon_dot[2] = '.';
	  drive_colon_dot[3] = '\0';

	  return g_strdup (drive_colon_dot);
	}
#endif
911
    return g_strdup (".");
912
913
    }

Tor Lillqvist's avatar
Tor Lillqvist committed
914
  while (base > file_name && G_IS_DIR_SEPARATOR (*base))
915
    base--;
916
917

#ifdef G_OS_WIN32
918
919
920
921
922
923
924
925
926
927
928
929
  /* base points to the char before the last slash.
   *
   * In case file_name is the root of a drive (X:\) or a child of the
   * root of a drive (X:\foo), include the slash.
   *
   * In case file_name is the root share of an UNC path
   * (\\server\share), add a slash, returning \\server\share\ .
   *
   * In case file_name is a direct child of a share in an UNC path
   * (\\server\share\foo), include the slash after the share name,
   * returning \\server\share\ .
   */
930
  if (base == file_name + 1 && g_ascii_isalpha (file_name[0]) && file_name[1] == ':')
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
    base++;
  else if (G_IS_DIR_SEPARATOR (file_name[0]) &&
	   G_IS_DIR_SEPARATOR (file_name[1]) &&
	   file_name[2] &&
	   !G_IS_DIR_SEPARATOR (file_name[2]) &&
	   base >= file_name + 2)
    {
      const gchar *p = file_name + 2;
      while (*p && !G_IS_DIR_SEPARATOR (*p))
	p++;
      if (p == base + 1)
	{
	  len = (guint) strlen (file_name) + 1;
	  base = g_new (gchar, len + 1);
	  strcpy (base, file_name);
	  base[len-1] = G_DIR_SEPARATOR;
	  base[len] = 0;
	  return base;
	}
      if (G_IS_DIR_SEPARATOR (*p))
	{
	  p++;
	  while (*p && !G_IS_DIR_SEPARATOR (*p))
	    p++;
	  if (p == base + 1)
	    base++;
	}
    }
959
960
#endif

961
  len = (guint) 1 + base - file_name;
Tim Janik's avatar
Tim Janik committed
962
  
963
964
965
  base = g_new (gchar, len + 1);
  g_memmove (base, file_name, len);
  base[len] = 0;
Tim Janik's avatar
Tim Janik committed
966
  
967
968
969
  return base;
}

Matthias Clasen's avatar
Matthias Clasen committed
970
971
972
973
974
975
976
977
978
/**
 * g_get_current_dir:
 *
 * Gets the current directory.
 * The returned string should be freed when no longer needed. The encoding 
 * of the returned string is system defined. On Windows, it is always UTF-8.
 * 
 * Returns: the current directory.
 */
979
gchar*
980
g_get_current_dir (void)
981
{
982
983
#ifdef G_OS_WIN32

984
  gchar *dir = NULL;
985
986
  wchar_t dummy[2], *wdir;
  int len;
987

988
989
  len = GetCurrentDirectoryW (2, dummy);
  wdir = g_new (wchar_t, len);
990

991
992
993
994
  if (GetCurrentDirectoryW (len, wdir) == len - 1)
    dir = g_utf16_to_utf8 (wdir, -1, NULL, NULL, NULL);
  
  g_free (wdir);
995

996
997
998
  if (dir == NULL)
    dir = g_strdup ("\\");

999
  return dir;
1000

1001
#else
1002
1003
1004
1005
1006
1007
1008
1009

  gchar *buffer = NULL;
  gchar *dir = NULL;
  static gulong max_len = 0;

  if (max_len == 0) 
    max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
  
1010
1011
1012
  /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
   * and, if that wasn't bad enough, hangs in doing so.
   */
1013
#if	(defined (sun) && !defined (__SVR4)) || !defined(HAVE_GETCWD)
1014
1015
  buffer = g_new (gchar, max_len + 1);
  *buffer = 0;
1016
  dir = getwd (buffer);
1017
#else	/* !sun || !HAVE_GETCWD */
1018
  while (max_len < G_MAXULONG / 2)
1019
    {
1020
      g_free (buffer);
1021
1022
1023
1024
1025
1026
1027
1028
1029
      buffer = g_new (gchar, max_len + 1);
      *buffer = 0;
      dir = getcwd (buffer, max_len);

      if (dir || errno != ERANGE)
	break;

      max_len *= 2;
    }
1030
#endif	/* !sun || !HAVE_GETCWD */
1031
  
1032
  if (!dir || !*buffer)
1033
    {
1034
1035
      /* hm, should we g_error() out here?
       * this can happen if e.g. "./" has mode \0000
1036
       */
1037
      buffer[0] = G_DIR_SEPARATOR;
1038
      buffer[1] = 0;
1039
    }
1040
1041
1042

  dir = g_strdup (buffer);
  g_free (buffer);
1043
  
1044
  return dir;
1045
#endif /* !Win32 */
1046
1047
}

Matthias Clasen's avatar
Matthias Clasen committed
1048
1049
/**
 * g_getenv:
1050
 * @variable: the environment variable to get, in the GLib file name encoding.
Matthias Clasen's avatar
Matthias Clasen committed
1051
 * 
1052
 * Returns the value of an environment variable. The name and value
Matthias Clasen's avatar
Matthias Clasen committed
1053
 * are in the GLib file name encoding. On UNIX, this means the actual
1054
1055
1056
1057
 * bytes which might or might not be in some consistent character set
 * and encoding. On Windows, it is in UTF-8. On Windows, in case the
 * environment variable's value contains references to other
 * environment variables, they are expanded.
Matthias Clasen's avatar
Matthias Clasen committed
1058
 * 
1059
1060
1061
1062
 * Return value: the value of the environment variable, or %NULL if
 * the environment variable is not found. The returned string may be
 * overwritten by the next call to g_getenv(), g_setenv() or
 * g_unsetenv().
Matthias Clasen's avatar
Matthias Clasen committed
1063
 **/
Havoc Pennington's avatar
Havoc Pennington committed
1064
G_CONST_RETURN gchar*
1065
1066
g_getenv (const gchar *variable)
{
1067
#ifndef G_OS_WIN32
1068

1069
1070
1071
  g_return_val_if_fail (variable != NULL, NULL);

  return getenv (variable);
1072
1073
1074

#else /* G_OS_WIN32 */

1075
  GQuark quark;
1076
  gchar *value;
1077
1078
  wchar_t dummy[2], *wname, *wvalue;
  int len;
1079
1080

  g_return_val_if_fail (variable != NULL, NULL);
1081
  g_return_val_if_fail (g_utf8_validate (variable, -1, NULL), NULL);
1082
1083
1084

  /* On Windows NT, it is relatively typical that environment
   * variables contain references to other environment variables. If
1085
1086
1087
1088
1089
1090
   * so, use ExpandEnvironmentStrings(). (In an ideal world, such
   * environment variables would be stored in the Registry as
   * REG_EXPAND_SZ type values, and would then get automatically
   * expanded before a program sees them. But there is broken software
   * that stores environment variables as REG_SZ values even if they
   * contain references to other environment variables.)
1091
1092
   */

1093
  wname = g_utf8_to_utf16 (variable, -1, NULL, NULL, NULL);
1094

1095
  len = GetEnvironmentVariableW (wname, dummy, 2);
1096

1097
1098
1099
1100
1101
1102
1103
  if (len == 0)
    {
      g_free (wname);
      return NULL;
    }
  else if (len == 1)
    len = 2;
1104

1105
  wvalue = g_new (wchar_t, len);
1106

1107
1108
  if (GetEnvironmentVariableW (wname, wvalue, len) != len - 1)
    {
1109
1110
      g_free (wname);
      g_free (wvalue);
1111
      return NULL;
1112
    }
1113

1114
1115
1116
  if (wcschr (wvalue, L'%') != NULL)
    {
      wchar_t *tem = wvalue;
1117

1118
      len = ExpandEnvironmentStringsW (wvalue, dummy, 2);
1119

1120
      if (len > 0)
1121
	{
1122
	  wvalue = g_new (wchar_t, len);
1123

1124
	  if (ExpandEnvironmentStringsW (tem, wvalue, len) != len)
1125
	    {
1126
1127
	      g_free (wvalue);
	      wvalue = tem;
1128
	    }
1129
1130
	  else
	    g_free (tem);
1131
	}
1132
    }
1133

1134
  value = g_utf16_to_utf8 (wvalue, -1, NULL, NULL, NULL);
1135

1136
1137
  g_free (wname);
  g_free (wvalue);
1138
1139
1140

  quark = g_quark_from_string (value);
  g_free (value);
1141
1142
  
  return g_quark_to_string (quark);
1143
1144

#endif /* G_OS_WIN32 */
1145
1146
}

1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
/* _g_getenv_nomalloc
 * this function does a getenv() without doing any kind of allocation
 * through glib. it's suitable for chars <= 127 only (both, for the
 * variable name and the contents) and for contents < 1024 chars in
 * length. also, it aliases "" to a NULL return value.
 **/
const gchar*
_g_getenv_nomalloc (const gchar *variable,
                    gchar        buffer[1024])
{
  const gchar *retval = getenv (variable);
  if (retval && retval[0])
    {
      gint l = strlen (retval);
      if (l < 1024)
        {
          strncpy (buffer, retval, l);
          buffer[l] = 0;
          return buffer;
        }
    }
  return NULL;
}

1171
1172
/**
 * g_setenv:
1173
 * @variable: the environment variable to set, must not contain '='.
1174
1175
1176
 * @value: the value for to set the variable to.
 * @overwrite: whether to change the variable if it already exists.
 *
1177
 * Sets an environment variable. Both the variable's name and value
Matthias Clasen's avatar
Matthias Clasen committed
1178
 * should be in the GLib file name encoding. On UNIX, this means that
1179
1180
 * they can be any sequence of bytes. On Windows, they should be in
 * UTF-8.
1181
 *
1182
1183
 * Note that on some systems, when variables are overwritten, the memory 
 * used for the previous variables and its value isn't reclaimed.
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
 *
 * Returns: %FALSE if the environment variable couldn't be set.
 *
 * Since: 2.4
 */
gboolean
g_setenv (const gchar *variable, 
	  const gchar *value, 
	  gboolean     overwrite)
{
1194
1195
#ifndef G_OS_WIN32

1196
  gint result;
1197
1198
1199
1200
#ifndef HAVE_SETENV
  gchar *string;
#endif

1201
  g_return_val_if_fail (variable != NULL, FALSE);
1202
  g_return_val_if_fail (strchr (variable, '=') == NULL, FALSE);
1203

1204
1205
1206
#ifdef HAVE_SETENV
  result = setenv (variable, value