3c2d617308120bdba77fe2fd52e62df82bb89539
[vlc.git] / src / misc / configuration.c
1 /*****************************************************************************
2  * configuration.c management of the modules configuration
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: configuration.c,v 1.61 2003/08/03 23:11:21 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <vlc/vlc.h>
25
26 #include <stdio.h>                                              /* sprintf() */
27 #include <stdlib.h>                                      /* free(), strtol() */
28 #include <string.h>                                              /* strdup() */
29 #ifdef HAVE_ERRNO_H
30 #   include <errno.h>                                               /* errno */
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #    include <unistd.h>                                          /* getuid() */
35 #endif
36
37 #ifdef HAVE_GETOPT_LONG
38 #   ifdef HAVE_GETOPT_H
39 #       include <getopt.h>                                       /* getopt() */
40 #   endif
41 #else
42 #   include "../extras/getopt.h"
43 #endif
44
45 #if defined(HAVE_GETPWUID)
46 #   include <pwd.h>                                            /* getpwuid() */
47 #endif
48
49 #if defined( HAVE_SYS_STAT_H )
50 #   include <sys/stat.h>
51 #endif
52 #if defined( HAVE_SYS_TYPES_H )
53 #   include <sys/types.h>
54 #endif
55 #if defined( WIN32 ) && !defined( UNDER_CE )
56 #   include <direct.h>
57 #endif
58
59 /*****************************************************************************
60  * config_GetType: get the type of a variable (bool, int, float, string)
61  *****************************************************************************
62  * This function is used to get the type of a variable from its name.
63  * Beware, this is quite slow.
64  *****************************************************************************/
65 int __config_GetType( vlc_object_t *p_this, const char *psz_name )
66 {
67     module_config_t *p_config;
68     int i_type;
69
70     p_config = config_FindConfig( p_this, psz_name );
71
72     /* sanity checks */
73     if( !p_config )
74     {
75         return 0;
76     }
77
78     switch( p_config->i_type )
79     {
80     case CONFIG_ITEM_BOOL:
81         i_type = VLC_VAR_BOOL;
82         break;
83
84     case CONFIG_ITEM_INTEGER:
85         i_type = VLC_VAR_INTEGER;
86         break;
87
88     case CONFIG_ITEM_FLOAT:
89         i_type = VLC_VAR_FLOAT;
90         break;
91
92     case CONFIG_ITEM_MODULE:
93     case CONFIG_ITEM_STRING:
94         i_type = VLC_VAR_STRING;
95         break;
96
97     case CONFIG_ITEM_FILE:
98         i_type = VLC_VAR_FILE;
99         break;
100
101     case CONFIG_ITEM_DIRECTORY:
102         i_type = VLC_VAR_DIRECTORY;
103         break;
104
105     default:
106         i_type = 0;
107         break;
108     }
109
110     return i_type;
111 }
112
113 /*****************************************************************************
114  * config_GetInt: get the value of an int variable
115  *****************************************************************************
116  * This function is used to get the value of variables which are internally
117  * represented by an integer (CONFIG_ITEM_INTEGER and
118  * CONFIG_ITEM_BOOL).
119  *****************************************************************************/
120 int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
121 {
122     module_config_t *p_config;
123
124     p_config = config_FindConfig( p_this, psz_name );
125
126     /* sanity checks */
127     if( !p_config )
128     {
129         msg_Err( p_this, "option %s does not exist", psz_name );
130         return -1;
131     }
132     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
133         (p_config->i_type!=CONFIG_ITEM_BOOL) )
134     {
135         msg_Err( p_this, "option %s does not refer to an int", psz_name );
136         return -1;
137     }
138
139     return p_config->i_value;
140 }
141
142 /*****************************************************************************
143  * config_GetFloat: get the value of a float variable
144  *****************************************************************************
145  * This function is used to get the value of variables which are internally
146  * represented by a float (CONFIG_ITEM_FLOAT).
147  *****************************************************************************/
148 float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
149 {
150     module_config_t *p_config;
151
152     p_config = config_FindConfig( p_this, psz_name );
153
154     /* sanity checks */
155     if( !p_config )
156     {
157         msg_Err( p_this, "option %s does not exist", psz_name );
158         return -1;
159     }
160     if( p_config->i_type != CONFIG_ITEM_FLOAT )
161     {
162         msg_Err( p_this, "option %s does not refer to a float", psz_name );
163         return -1;
164     }
165
166     return p_config->f_value;
167 }
168
169 /*****************************************************************************
170  * config_GetPsz: get the string value of a string variable
171  *****************************************************************************
172  * This function is used to get the value of variables which are internally
173  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
174  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
175  *
176  * Important note: remember to free() the returned char* because it's a
177  *   duplicate of the actual value. It isn't safe to return a pointer to the
178  *   actual value as it can be modified at any time.
179  *****************************************************************************/
180 char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
181 {
182     module_config_t *p_config;
183     char *psz_value = NULL;
184
185     p_config = config_FindConfig( p_this, psz_name );
186
187     /* sanity checks */
188     if( !p_config )
189     {
190         msg_Err( p_this, "option %s does not exist", psz_name );
191         return NULL;
192     }
193     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
194         (p_config->i_type!=CONFIG_ITEM_FILE) &&
195         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
196         (p_config->i_type!=CONFIG_ITEM_MODULE) )
197     {
198         msg_Err( p_this, "option %s does not refer to a string", psz_name );
199         return NULL;
200     }
201
202     /* return a copy of the string */
203     vlc_mutex_lock( p_config->p_lock );
204     if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
205     vlc_mutex_unlock( p_config->p_lock );
206
207     return psz_value;
208 }
209
210 /*****************************************************************************
211  * config_PutPsz: set the string value of a string variable
212  *****************************************************************************
213  * This function is used to set the value of variables which are internally
214  * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
215  * CONFIG_ITEM_DIRECTORY, and CONFIG_ITEM_MODULE).
216  *****************************************************************************/
217 void __config_PutPsz( vlc_object_t *p_this,
218                       const char *psz_name, const char *psz_value )
219 {
220     module_config_t *p_config;
221     vlc_value_t oldval, val;
222
223     p_config = config_FindConfig( p_this, psz_name );
224
225     /* sanity checks */
226     if( !p_config )
227     {
228         msg_Warn( p_this, "option %s does not exist", psz_name );
229         return;
230     }
231     if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
232         (p_config->i_type!=CONFIG_ITEM_FILE) &&
233         (p_config->i_type!=CONFIG_ITEM_DIRECTORY) &&
234         (p_config->i_type!=CONFIG_ITEM_MODULE) )
235     {
236         msg_Err( p_this, "option %s does not refer to a string", psz_name );
237         return;
238     }
239
240     vlc_mutex_lock( p_config->p_lock );
241
242     /* backup old value */
243     oldval.psz_string = p_config->psz_value;
244
245     if( psz_value && *psz_value ) p_config->psz_value = strdup( psz_value );
246     else p_config->psz_value = NULL;
247
248     val.psz_string = p_config->psz_value;
249
250     vlc_mutex_unlock( p_config->p_lock );
251
252     if( p_config->pf_callback )
253     {
254         p_config->pf_callback( p_this, psz_name, oldval, val,
255                                p_config->p_callback_data );
256     }
257
258     /* free old string */
259     if( oldval.psz_string ) free( oldval.psz_string );
260 }
261
262 /*****************************************************************************
263  * config_PutInt: set the integer value of an int variable
264  *****************************************************************************
265  * This function is used to set the value of variables which are internally
266  * represented by an integer (CONFIG_ITEM_INTEGER and
267  * CONFIG_ITEM_BOOL).
268  *****************************************************************************/
269 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
270 {
271     module_config_t *p_config;
272     vlc_value_t oldval, val;
273
274     p_config = config_FindConfig( p_this, psz_name );
275
276     /* sanity checks */
277     if( !p_config )
278     {
279         msg_Warn( p_this, "option %s does not exist", psz_name );
280         return;
281     }
282     if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
283         (p_config->i_type!=CONFIG_ITEM_BOOL) )
284     {
285         msg_Err( p_this, "option %s does not refer to an int", psz_name );
286         return;
287     }
288
289     /* backup old value */
290     oldval.i_int = p_config->i_value;
291
292     /* if i_min == i_max == 0, then do not use them */
293     if ((p_config->i_min == 0) && (p_config->i_max == 0))
294     {
295         p_config->i_value = i_value;
296     }
297     else if (i_value < p_config->i_min)
298     {
299         p_config->i_value = p_config->i_min;
300     }
301     else if (i_value > p_config->i_max)
302     {
303         p_config->i_value = p_config->i_max;
304     }
305     else
306     {
307         p_config->i_value = i_value;
308     }
309
310     val.i_int = p_config->i_value;
311
312     if( p_config->pf_callback )
313     {
314         p_config->pf_callback( p_this, psz_name, oldval, val,
315                                p_config->p_callback_data );
316     }
317 }
318
319 /*****************************************************************************
320  * config_PutFloat: set the value of a float variable
321  *****************************************************************************
322  * This function is used to set the value of variables which are internally
323  * represented by a float (CONFIG_ITEM_FLOAT).
324  *****************************************************************************/
325 void __config_PutFloat( vlc_object_t *p_this,
326                         const char *psz_name, float f_value )
327 {
328     module_config_t *p_config;
329     vlc_value_t oldval, val;
330
331     p_config = config_FindConfig( p_this, psz_name );
332
333     /* sanity checks */
334     if( !p_config )
335     {
336         msg_Warn( p_this, "option %s does not exist", psz_name );
337         return;
338     }
339     if( p_config->i_type != CONFIG_ITEM_FLOAT )
340     {
341         msg_Err( p_this, "option %s does not refer to a float", psz_name );
342         return;
343     }
344
345     /* backup old value */
346     oldval.f_float = p_config->f_value;
347
348     /* if f_min == f_max == 0, then do not use them */
349     if ((p_config->f_min == 0) && (p_config->f_max == 0))
350     {
351         p_config->f_value = f_value;
352     }
353     else if (f_value < p_config->f_min)
354     {
355         p_config->f_value = p_config->f_min;
356     }
357     else if (f_value > p_config->f_max)
358     {
359         p_config->f_value = p_config->f_max;
360     }
361     else
362     {
363         p_config->f_value = f_value;
364     }
365
366     val.f_float = p_config->f_value;
367
368     if( p_config->pf_callback )
369     {
370         p_config->pf_callback( p_this, psz_name, oldval, val,
371                                p_config->p_callback_data );
372     }
373 }
374
375 /*****************************************************************************
376  * config_FindConfig: find the config structure associated with an option.
377  *****************************************************************************
378  * FIXME: This function really needs to be optimized.
379  * FIXME: And now even more.
380  *****************************************************************************/
381 module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
382 {
383     vlc_list_t *p_list;
384     module_t *p_parser;
385     module_config_t *p_item;
386     int i_index;
387
388     if( !psz_name ) return NULL;
389
390     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
391
392     for( i_index = 0; i_index < p_list->i_count; i_index++ )
393     {
394         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
395
396         if( !p_parser->i_config_items )
397             continue;
398
399         for( p_item = p_parser->p_config;
400              p_item->i_type != CONFIG_HINT_END;
401              p_item++ )
402         {
403             if( p_item->i_type & CONFIG_HINT )
404                 /* ignore hints */
405                 continue;
406             if( !strcmp( psz_name, p_item->psz_name ) )
407             {
408                 vlc_list_release( p_list );
409                 return p_item;
410             }
411         }
412     }
413
414     vlc_list_release( p_list );
415
416     return NULL;
417 }
418
419 /*****************************************************************************
420  * config_Duplicate: creates a duplicate of a module's configuration data.
421  *****************************************************************************
422  * Unfortunatly we cannot work directly with the module's config data as
423  * this module might be unloaded from memory at any time (remember HideModule).
424  * This is why we need to create an exact copy of the config data.
425  *****************************************************************************/
426 void config_Duplicate( module_t *p_module, module_config_t *p_orig )
427 {
428     int i, j, i_lines = 1;
429     module_config_t *p_item;
430
431     /* Calculate the structure length */
432     p_module->i_config_items = 0;
433     p_module->i_bool_items = 0;
434
435     for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
436     {
437         i_lines++;
438
439         if( p_item->i_type & CONFIG_ITEM )
440         {
441             p_module->i_config_items++;
442         }
443
444         if( p_item->i_type == CONFIG_ITEM_BOOL )
445         {
446             p_module->i_bool_items++;
447         }
448     }
449
450     /* Allocate memory */
451     p_module->p_config = (module_config_t *)malloc( sizeof(module_config_t)
452                                                      * i_lines );
453     if( p_module->p_config == NULL )
454     {
455         msg_Err( p_module, "config error: can't duplicate p_config" );
456         return;
457     }
458
459     /* Do the duplication job */
460     for( i = 0; i < i_lines ; i++ )
461     {
462         p_module->p_config[i].i_type = p_orig[i].i_type;
463         p_module->p_config[i].i_short = p_orig[i].i_short;
464         p_module->p_config[i].i_value = p_orig[i].i_value;
465         p_module->p_config[i].i_value_orig = p_orig[i].i_value;
466         p_module->p_config[i].i_min = p_orig[i].i_min;
467         p_module->p_config[i].i_max = p_orig[i].i_max;
468         p_module->p_config[i].f_value = p_orig[i].f_value;
469         p_module->p_config[i].f_value_orig = p_orig[i].f_value;
470         p_module->p_config[i].f_min = p_orig[i].f_min;
471         p_module->p_config[i].f_max = p_orig[i].f_max;
472         p_module->p_config[i].b_dirty = p_orig[i].b_dirty;
473         p_module->p_config[i].b_advanced = p_orig[i].b_advanced;
474
475         p_module->p_config[i].psz_type = p_orig[i].psz_type ?
476                                    strdup( p_orig[i].psz_type ) : NULL;
477         p_module->p_config[i].psz_name = p_orig[i].psz_name ?
478                                    strdup( p_orig[i].psz_name ) : NULL;
479         p_module->p_config[i].psz_text = p_orig[i].psz_text ?
480                                    strdup( _(p_orig[i].psz_text) ) : NULL;
481         p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
482                                    strdup( _(p_orig[i].psz_longtext) ) : NULL;
483         p_module->p_config[i].psz_value = p_orig[i].psz_value ?
484                                    strdup( p_orig[i].psz_value ) : NULL;
485         p_module->p_config[i].psz_value_orig = p_orig[i].psz_value ?
486                                    strdup( p_orig[i].psz_value ) : NULL;
487
488         p_module->p_config[i].p_lock = &p_module->object_lock;
489
490         /* duplicate the string list */
491         p_module->p_config[i].ppsz_list = NULL;
492         if( p_orig[i].ppsz_list )
493         {
494             for( j = 0; p_orig[i].ppsz_list[j]; j++ );
495             p_module->p_config[i].ppsz_list = malloc( (j+1) *sizeof(char *) );
496             if( p_module->p_config[i].ppsz_list )
497             {
498                 for( j = 0; p_orig[i].ppsz_list[j]; j++ )
499                     p_module->p_config[i].ppsz_list[j] =
500                         strdup( p_orig[i].ppsz_list[j] );
501             }
502             p_module->p_config[i].ppsz_list[j] = NULL;
503         }
504
505         p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
506     }
507 }
508
509 /*****************************************************************************
510  * config_Free: frees a duplicated module's configuration data.
511  *****************************************************************************
512  * This function frees all the data duplicated by config_Duplicate.
513  *****************************************************************************/
514 void config_Free( module_t *p_module )
515 {
516     module_config_t *p_item = p_module->p_config;
517     int i;
518
519     if( p_item == NULL )
520     {
521         return;
522     }
523
524     for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
525     {
526         if( p_item->psz_type )
527             free( p_item->psz_type );
528
529         if( p_item->psz_name )
530             free( p_item->psz_name );
531
532         if( p_item->psz_text )
533             free( p_item->psz_text );
534
535         if( p_item->psz_longtext )
536             free( p_item->psz_longtext );
537
538         if( p_item->psz_value )
539             free( p_item->psz_value );
540
541         if( p_item->psz_value_orig )
542             free( p_item->psz_value_orig );
543
544         if( p_item->ppsz_list )
545         {
546             for( i = 0; p_item->ppsz_list[i]; i++ )
547                 free(p_item->ppsz_list[i]);
548             free( p_item->ppsz_list );
549         }
550     }
551
552     free( p_module->p_config );
553     p_module->p_config = NULL;
554 }
555
556 /*****************************************************************************
557  * config_SetCallbacks: sets callback functions in the duplicate p_config.
558  *****************************************************************************
559  * Unfortunatly we cannot work directly with the module's config data as
560  * this module might be unloaded from memory at any time (remember HideModule).
561  * This is why we need to duplicate callbacks each time we reload the module.
562  *****************************************************************************/
563 void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig )
564 {
565     while( p_new->i_type != CONFIG_HINT_END )
566     {
567         p_new->pf_callback = p_orig->pf_callback;
568         p_new++;
569         p_orig++;
570     }
571 }
572
573 /*****************************************************************************
574  * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
575  *****************************************************************************
576  * We simply undo what we did in config_SetCallbacks.
577  *****************************************************************************/
578 void config_UnsetCallbacks( module_config_t *p_new )
579 {
580     while( p_new->i_type != CONFIG_HINT_END )
581     {
582         p_new->pf_callback = NULL;
583         p_new++;
584     }
585 }
586
587 /*****************************************************************************
588  * config_ResetAll: reset the configuration data for all the modules.
589  *****************************************************************************/
590 void __config_ResetAll( vlc_object_t *p_this )
591 {
592     int i_index, i;
593     vlc_list_t *p_list;
594     module_t *p_module;
595
596     /* Acquire config file lock */
597     vlc_mutex_lock( &p_this->p_vlc->config_lock );
598
599     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
600
601     for( i_index = 0; i_index < p_list->i_count; i_index++ )
602     {
603         p_module = (module_t *)p_list->p_values[i_index].p_object ;
604         if( p_module->b_submodule ) continue;
605
606         for( i = 0; p_module->p_config[i].i_type != CONFIG_HINT_END; i++ )
607         {
608             p_module->p_config[i].i_value = p_module->p_config[i].i_value_orig;
609             p_module->p_config[i].f_value = p_module->p_config[i].f_value_orig;
610             if( p_module->p_config[i].psz_value )
611                 free( p_module->p_config[i].psz_value );
612             p_module->p_config[i].psz_value =
613                 p_module->p_config[i].psz_value_orig ?
614                 strdup( p_module->p_config[i].psz_value_orig ) : NULL;
615         }
616     }
617
618     vlc_list_release( p_list );
619     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
620 }
621
622 /*****************************************************************************
623  * config_LoadConfigFile: loads the configuration file.
624  *****************************************************************************
625  * This function is called to load the config options stored in the config
626  * file.
627  *****************************************************************************/
628 int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
629 {
630     vlc_list_t *p_list;
631     module_t *p_parser;
632     module_config_t *p_item;
633     FILE *file;
634     char line[1024];
635     char *p_index, *psz_option_name, *psz_option_value;
636     char *psz_filename, *psz_homedir;
637     int i_index;
638
639     psz_homedir = p_this->p_vlc->psz_homedir;
640     if( !psz_homedir )
641     {
642         msg_Err( p_this, "psz_homedir is null" );
643         return -1;
644     }
645     psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
646                                    strlen(psz_homedir) + 1 );
647     if( !psz_filename )
648     {
649         msg_Err( p_this, "out of memory" );
650         return -1;
651     }
652     sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
653
654     msg_Dbg( p_this, "opening config file %s", psz_filename );
655
656     /* Acquire config file lock */
657     vlc_mutex_lock( &p_this->p_vlc->config_lock );
658
659     file = fopen( psz_filename, "rt" );
660     if( !file )
661     {
662         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
663         free( psz_filename );
664         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
665         return -1;
666     }
667
668     /* Look for the selected module, if NULL then save everything */
669     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
670
671     for( i_index = 0; i_index < p_list->i_count; i_index++ )
672     {
673         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
674
675         if( psz_module_name
676              && strcmp( psz_module_name, p_parser->psz_object_name ) )
677         {
678             continue;
679         }
680
681         /* The config file is organized in sections, one per module. Look for
682          * the interesting section ( a section is of the form [foo] ) */
683         fseek( file, 0L, SEEK_SET );
684         while( fgets( line, 1024, file ) )
685         {
686             if( (line[0] == '[')
687                && (p_index = strchr(line,']'))
688                && (p_index - &line[1]
689                     == (int)strlen(p_parser->psz_object_name))
690                && !memcmp( &line[1], p_parser->psz_object_name,
691                            strlen(p_parser->psz_object_name) ) )
692             {
693 #if 0
694                 msg_Dbg( p_this, "loading config for module \"%s\"",
695                                  p_parser->psz_object_name );
696 #endif
697
698                 break;
699             }
700         }
701         /* either we found the section or we're at the EOF */
702
703         /* Now try to load the options in this section */
704         while( fgets( line, 1024, file ) )
705         {
706             if( line[0] == '[' ) break; /* end of section */
707
708             /* ignore comments or empty lines */
709             if( (line[0] == '#') || (line[0] == '\n') || (line[0] == (char)0) )
710                 continue;
711
712             /* get rid of line feed */
713             if( line[strlen(line)-1] == '\n' )
714                 line[strlen(line)-1] = (char)0;
715
716             /* look for option name */
717             psz_option_name = line;
718             psz_option_value = NULL;
719             p_index = strchr( line, '=' );
720             if( !p_index ) break; /* this ain't an option!!! */
721
722             *p_index = (char)0;
723             psz_option_value = p_index + 1;
724
725             if( !p_parser->i_config_items )
726             {
727                 continue;
728             }
729
730             /* try to match this option with one of the module's options */
731             for( p_item = p_parser->p_config;
732                  p_item->i_type != CONFIG_HINT_END;
733                  p_item++ )
734             {
735                 if( p_item->i_type & CONFIG_HINT )
736                     /* ignore hints */
737                     continue;
738
739                 if( !strcmp( p_item->psz_name, psz_option_name ) )
740                 {
741                     /* We found it */
742                     switch( p_item->i_type )
743                     {
744                     case CONFIG_ITEM_BOOL:
745                     case CONFIG_ITEM_INTEGER:
746                         if( !*psz_option_value )
747                             break;                    /* ignore empty option */
748                         p_item->i_value = atoi( psz_option_value);
749 #if 0
750                         msg_Dbg( p_this, "option \"%s\", value %i",
751                                  p_item->psz_name, p_item->i_value );
752 #endif
753                         break;
754
755                     case CONFIG_ITEM_FLOAT:
756                         if( !*psz_option_value )
757                             break;                    /* ignore empty option */
758                         p_item->f_value = (float)atof( psz_option_value);
759 #if O
760                         msg_Dbg( p_this, "option \"%s\", value %f",
761                                  p_item->psz_name, (double)p_item->f_value );
762 #endif
763                         break;
764
765                     default:
766                         vlc_mutex_lock( p_item->p_lock );
767
768                         /* free old string */
769                         if( p_item->psz_value )
770                             free( p_item->psz_value );
771
772                         p_item->psz_value = *psz_option_value ?
773                             strdup( psz_option_value ) : NULL;
774
775                         vlc_mutex_unlock( p_item->p_lock );
776
777 #if 0
778                         msg_Dbg( p_this, "option \"%s\", value \"%s\"",
779                                  p_item->psz_name,
780                                  p_item->psz_value ? p_item->psz_value : "" );
781 #endif
782                         break;
783                     }
784                 }
785             }
786         }
787
788     }
789
790     vlc_list_release( p_list );
791
792     fclose( file );
793     free( psz_filename );
794
795     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
796
797     return 0;
798 }
799
800 /*****************************************************************************
801  * config_SaveConfigFile: Save a module's config options.
802  *****************************************************************************
803  * This will save the specified module's config options to the config file.
804  * If psz_module_name is NULL then we save all the modules config options.
805  * It's no use to save the config options that kept their default values, so
806  * we'll try to be a bit clever here.
807  *
808  * When we save we mustn't delete the config options of the modules that
809  * haven't been loaded. So we cannot just create a new config file with the
810  * config structures we've got in memory.
811  * I don't really know how to deal with this nicely, so I will use a completly
812  * dumb method ;-)
813  * I will load the config file in memory, but skipping all the sections of the
814  * modules we want to save. Then I will create a brand new file, dump the file
815  * loaded in memory and then append the sections of the modules we want to
816  * save.
817  * Really stupid no ?
818  *****************************************************************************/
819 int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
820 {
821     module_t *p_parser;
822     vlc_list_t *p_list;
823     module_config_t *p_item;
824     FILE *file;
825     char p_line[1024], *p_index2;
826     int i_sizebuf = 0;
827     char *p_bigbuffer, *p_index;
828     vlc_bool_t b_backup;
829     char *psz_filename, *psz_homedir;
830     int i_index;
831
832     /* Acquire config file lock */
833     vlc_mutex_lock( &p_this->p_vlc->config_lock );
834
835     psz_homedir = p_this->p_vlc->psz_homedir;
836     if( !psz_homedir )
837     {
838         msg_Err( p_this, "psz_homedir is null" );
839         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
840         return -1;
841     }
842     psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
843                                    strlen(psz_homedir) + 1 );
844     if( !psz_filename )
845     {
846         msg_Err( p_this, "out of memory" );
847         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
848         return -1;
849     }
850     sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
851
852 #if defined( UNDER_CE )
853     {
854         wchar_t psz_new[ MAX_PATH ];
855         MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new, MAX_PATH );
856         if( CreateDirectory( psz_new, NULL ) )
857         {
858             msg_Err( p_this, "could not create %s", psz_filename );
859         }
860     }
861
862 #elif defined( HAVE_ERRNO_H )
863 #   if defined( WIN32 )
864     if( mkdir( psz_filename ) && errno != EEXIST )
865 #   else
866     if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
867 #   endif
868     {
869         msg_Err( p_this, "could not create %s (%s)",
870                          psz_filename, strerror(errno) );
871     }
872
873 #else
874     if( mkdir( psz_filename ) )
875     {
876         msg_Err( p_this, "could not create %s", psz_filename );
877     }
878
879 #endif
880
881     strcat( psz_filename, "/" CONFIG_FILE );
882
883
884     msg_Dbg( p_this, "opening config file %s", psz_filename );
885
886     file = fopen( psz_filename, "rt" );
887     if( !file )
888     {
889         msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
890     }
891     else
892     {
893         /* look for file size */
894         fseek( file, 0L, SEEK_END );
895         i_sizebuf = ftell( file );
896         fseek( file, 0L, SEEK_SET );
897     }
898
899     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
900     if( !p_bigbuffer )
901     {
902         msg_Err( p_this, "out of memory" );
903         if( file ) fclose( file );
904         free( psz_filename );
905         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
906         return -1;
907     }
908     p_bigbuffer[0] = 0;
909
910     /* List all available modules */
911     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
912
913     /* backup file into memory, we only need to backup the sections we won't
914      * save later on */
915     b_backup = 0;
916     while( file && fgets( p_line, 1024, file ) )
917     {
918         if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
919         {
920
921             /* we found a section, check if we need to do a backup */
922             for( i_index = 0; i_index < p_list->i_count; i_index++ )
923             {
924                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
925
926                 if( ((p_index2 - &p_line[1])
927                        == (int)strlen(p_parser->psz_object_name) )
928                     && !memcmp( &p_line[1], p_parser->psz_object_name,
929                                 strlen(p_parser->psz_object_name) ) )
930                 {
931                     if( !psz_module_name )
932                         break;
933                     else if( !strcmp( psz_module_name,
934                                       p_parser->psz_object_name ) )
935                         break;
936                 }
937             }
938
939             if( i_index == p_list->i_count )
940             {
941                 /* we don't have this section in our list so we need to back
942                  * it up */
943                 *p_index2 = 0;
944                 msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
945                                  &p_line[1] );
946                 *p_index2 = ']';
947
948                 b_backup = 1;
949             }
950             else
951             {
952                 b_backup = 0;
953             }
954         }
955
956         /* save line if requested and line is valid (doesn't begin with a
957          * space, tab, or eol) */
958         if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
959             && (p_line[0] != '\t') )
960         {
961             strcpy( p_index, p_line );
962             p_index += strlen( p_line );
963         }
964     }
965     if( file ) fclose( file );
966
967
968     /*
969      * Save module config in file
970      */
971
972     file = fopen( psz_filename, "wt" );
973     if( !file )
974     {
975         msg_Warn( p_this, "could not open config file %s for writing",
976                           psz_filename );
977         free( psz_filename );
978         vlc_list_release( p_list );
979         vlc_mutex_unlock( &p_this->p_vlc->config_lock );
980         return -1;
981     }
982
983     fprintf( file, "###\n###  " COPYRIGHT_MESSAGE "\n###\n\n" );
984
985     /* Look for the selected module, if NULL then save everything */
986     for( i_index = 0; i_index < p_list->i_count; i_index++ )
987     {
988         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
989
990         if( psz_module_name && strcmp( psz_module_name,
991                                        p_parser->psz_object_name ) )
992             continue;
993
994         if( !p_parser->i_config_items )
995             continue;
996
997         msg_Dbg( p_this, "saving config for module \"%s\"",
998                          p_parser->psz_object_name );
999
1000         fprintf( file, "[%s]", p_parser->psz_object_name );
1001         if( p_parser->psz_longname )
1002             fprintf( file, " # %s\n\n", p_parser->psz_longname );
1003         else
1004             fprintf( file, "\n\n" );
1005
1006         for( p_item = p_parser->p_config;
1007              p_item->i_type != CONFIG_HINT_END;
1008              p_item++ )
1009         {
1010             if( p_item->i_type & CONFIG_HINT )
1011                 /* ignore hints */
1012                 continue;
1013
1014             switch( p_item->i_type )
1015             {
1016             case CONFIG_ITEM_BOOL:
1017             case CONFIG_ITEM_INTEGER:
1018                 if( p_item->psz_text )
1019                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
1020                              (p_item->i_type == CONFIG_ITEM_BOOL) ?
1021                              _("boolean") : _("integer") );
1022                 if( p_item->i_value == p_item->i_value_orig )
1023                     fprintf( file, "#" );
1024                 fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
1025                 break;
1026
1027             case CONFIG_ITEM_FLOAT:
1028                 if( p_item->psz_text )
1029                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
1030                              _("float") );
1031                 if( p_item->f_value == p_item->f_value_orig )
1032                     fprintf( file, "#" );
1033                 fprintf( file, "%s=%f\n", p_item->psz_name,
1034                          (double)p_item->f_value );
1035                 break;
1036
1037             default:
1038                 if( p_item->psz_text )
1039                     fprintf( file, "# %s (%s)\n", p_item->psz_text,
1040                              _("string") );
1041                 if( (!p_item->psz_value && !p_item->psz_value_orig) ||
1042                     (p_item->psz_value && p_item->psz_value_orig &&
1043                      !strcmp( p_item->psz_value, p_item->psz_value_orig )) )
1044                     fprintf( file, "#" );
1045                 fprintf( file, "%s=%s\n", p_item->psz_name,
1046                          p_item->psz_value ? p_item->psz_value : "" );
1047             }
1048         }
1049
1050         fprintf( file, "\n" );
1051     }
1052
1053     vlc_list_release( p_list );
1054
1055     /*
1056      * Restore old settings from the config in file
1057      */
1058     fputs( p_bigbuffer, file );
1059     free( p_bigbuffer );
1060
1061     fclose( file );
1062     free( psz_filename );
1063     vlc_mutex_unlock( &p_this->p_vlc->config_lock );
1064
1065     return 0;
1066 }
1067
1068 /*****************************************************************************
1069  * config_LoadCmdLine: parse command line
1070  *****************************************************************************
1071  * Parse command line for configuration options.
1072  * Now that the module_bank has been initialized, we can dynamically
1073  * generate the longopts structure used by getops. We have to do it this way
1074  * because we don't know (and don't want to know) in advance the configuration
1075  * options used (ie. exported) by each module.
1076  *****************************************************************************/
1077 int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
1078                           vlc_bool_t b_ignore_errors )
1079 {
1080     int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
1081     module_t *p_parser;
1082     vlc_list_t *p_list;
1083     module_config_t *p_item;
1084     struct option *p_longopts;
1085     int i_modules_index;
1086
1087     /* Short options */
1088     module_config_t *pp_shortopts[256];
1089     char *psz_shortopts;
1090
1091     /* Set default configuration and copy arguments */
1092     p_this->p_vlc->i_argc    = *pi_argc;
1093     p_this->p_vlc->ppsz_argv = ppsz_argv;
1094
1095     p_this->p_vlc->p_channel = NULL;
1096
1097 #ifdef SYS_DARWIN
1098     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
1099      * is the PSN - process serial number (a unique PID-ish thingie)
1100      * still ok for real Darwin & when run from command line */
1101     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
1102                                         /* for example -psn_0_9306113 */
1103     {
1104         /* GDMF!... I can't do this or else the MacOSX window server will
1105          * not pick up the PSN and not register the app and we crash...
1106          * hence the following kludge otherwise we'll get confused w/ argv[1]
1107          * being an input file name */
1108 #if 0
1109         ppsz_argv[ 1 ] = NULL;
1110 #endif
1111         *pi_argc = *pi_argc - 1;
1112         pi_argc--;
1113         return 0;
1114     }
1115 #endif
1116
1117     /* List all modules */
1118     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1119
1120     /*
1121      * Generate the longopts and shortopts structures used by getopt_long
1122      */
1123
1124     i_opts = 0;
1125     for( i_modules_index = 0; i_modules_index < p_list->i_count;
1126          i_modules_index++ )
1127     {
1128         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
1129
1130         /* count the number of exported configuration options (to allocate
1131          * longopts). We also need to allocate space for too options when
1132          * dealing with boolean to allow for --foo and --no-foo */
1133         i_opts += p_parser->i_config_items
1134                      + 2 * p_parser->i_bool_items;
1135     }
1136
1137     p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
1138     if( p_longopts == NULL )
1139     {
1140         msg_Err( p_this, "out of memory" );
1141         vlc_list_release( p_list );
1142         return -1;
1143     }
1144
1145     psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
1146     if( psz_shortopts == NULL )
1147     {
1148         msg_Err( p_this, "out of memory" );
1149         free( p_longopts );
1150         vlc_list_release( p_list );
1151         return -1;
1152     }
1153
1154     /* If we are requested to ignore errors, then we must work on a copy
1155      * of the ppsz_argv array, otherwise getopt_long will reorder it for
1156      * us, ignoring the arity of the options */
1157     if( b_ignore_errors )
1158     {
1159         ppsz_argv = (char**)malloc( *pi_argc * sizeof(char *) );
1160         if( ppsz_argv == NULL )
1161         {
1162             msg_Err( p_this, "out of memory" );
1163             free( psz_shortopts );
1164             free( p_longopts );
1165             vlc_list_release( p_list );
1166             return -1;
1167         }
1168         memcpy( ppsz_argv, p_this->p_vlc->ppsz_argv,
1169                 *pi_argc * sizeof(char *) );
1170     }
1171
1172     i_shortopts = 0;
1173     for( i_index = 0; i_index < 256; i_index++ )
1174     {
1175         pp_shortopts[i_index] = NULL;
1176     }
1177
1178     /* Fill the p_longopts and psz_shortopts structures */
1179     i_index = 0;
1180     for( i_modules_index = 0; i_modules_index < p_list->i_count;
1181          i_modules_index++ )
1182     {
1183         p_parser = (module_t *)p_list->p_values[i_modules_index].p_object ;
1184
1185         if( !p_parser->i_config_items )
1186             continue;
1187
1188         for( p_item = p_parser->p_config;
1189              p_item->i_type != CONFIG_HINT_END;
1190              p_item++ )
1191         {
1192             /* Ignore hints */
1193             if( p_item->i_type & CONFIG_HINT )
1194                 continue;
1195
1196             /* Add item to long options */
1197             p_longopts[i_index].name = strdup( p_item->psz_name );
1198             if( p_longopts[i_index].name == NULL ) continue;
1199             p_longopts[i_index].has_arg =
1200                 (p_item->i_type == CONFIG_ITEM_BOOL)?
1201                                                no_argument : required_argument;
1202             p_longopts[i_index].flag = &flag;
1203             p_longopts[i_index].val = 0;
1204             i_index++;
1205
1206             /* When dealing with bools we also need to add the --no-foo
1207              * option */
1208             if( p_item->i_type == CONFIG_ITEM_BOOL )
1209             {
1210                 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
1211                 if( psz_name == NULL ) continue;
1212                 strcpy( psz_name, "no" );
1213                 strcat( psz_name, p_item->psz_name );
1214
1215                 p_longopts[i_index].name = psz_name;
1216                 p_longopts[i_index].has_arg = no_argument;
1217                 p_longopts[i_index].flag = &flag;
1218                 p_longopts[i_index].val = 1;
1219                 i_index++;
1220
1221                 psz_name = malloc( strlen(p_item->psz_name) + 4 );
1222                 if( psz_name == NULL ) continue;
1223                 strcpy( psz_name, "no-" );
1224                 strcat( psz_name, p_item->psz_name );
1225
1226                 p_longopts[i_index].name = psz_name;
1227                 p_longopts[i_index].has_arg = no_argument;
1228                 p_longopts[i_index].flag = &flag;
1229                 p_longopts[i_index].val = 1;
1230                 i_index++;
1231             }
1232
1233             /* If item also has a short option, add it */
1234             if( p_item->i_short )
1235             {
1236                 pp_shortopts[(int)p_item->i_short] = p_item;
1237                 psz_shortopts[i_shortopts] = p_item->i_short;
1238                 i_shortopts++;
1239                 if( p_item->i_type != CONFIG_ITEM_BOOL )
1240                 {
1241                     psz_shortopts[i_shortopts] = ':';
1242                     i_shortopts++;
1243
1244                     if( p_item->i_short == 'v' )
1245                     {
1246                         psz_shortopts[i_shortopts] = ':';
1247                         i_shortopts++;
1248                     }
1249                 }
1250             }
1251         }
1252     }
1253
1254     /* We don't need the module list anymore */
1255     vlc_list_release( p_list );
1256
1257     /* Close the longopts and shortopts structures */
1258     memset( &p_longopts[i_index], 0, sizeof(struct option) );
1259     psz_shortopts[i_shortopts] = '\0';
1260
1261     /*
1262      * Parse the command line options
1263      */
1264     opterr = 0;
1265     optind = 1;
1266     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
1267                                   p_longopts, &i_index ) ) != EOF )
1268     {
1269         /* A long option has been recognized */
1270         if( i_cmd == 0 )
1271         {
1272             module_config_t *p_conf;
1273             char *psz_name = (char *)p_longopts[i_index].name;
1274
1275             /* Check if we deal with a --nofoo or --no-foo long option */
1276             if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
1277
1278             /* Store the configuration option */
1279             p_conf = config_FindConfig( p_this, psz_name );
1280
1281             if( p_conf ) switch( p_conf->i_type )
1282             {
1283             case CONFIG_ITEM_STRING:
1284             case CONFIG_ITEM_FILE:
1285             case CONFIG_ITEM_DIRECTORY:
1286             case CONFIG_ITEM_MODULE:
1287                 config_PutPsz( p_this, psz_name, optarg );
1288                 break;
1289             case CONFIG_ITEM_INTEGER:
1290                 config_PutInt( p_this, psz_name, atoi(optarg));
1291                 break;
1292             case CONFIG_ITEM_FLOAT:
1293                 config_PutFloat( p_this, psz_name, (float)atof(optarg) );
1294                 break;
1295             case CONFIG_ITEM_BOOL:
1296                 config_PutInt( p_this, psz_name, !flag );
1297                 break;
1298             }
1299
1300             continue;
1301         }
1302
1303         /* A short option has been recognized */
1304         if( pp_shortopts[i_cmd] != NULL )
1305         {
1306             switch( pp_shortopts[i_cmd]->i_type )
1307             {
1308             case CONFIG_ITEM_STRING:
1309             case CONFIG_ITEM_FILE:
1310             case CONFIG_ITEM_DIRECTORY:
1311             case CONFIG_ITEM_MODULE:
1312                 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
1313                 break;
1314             case CONFIG_ITEM_INTEGER:
1315                 if( i_cmd == 'v' )
1316                 {
1317                     if( optarg )
1318                     {
1319                         if( *optarg == 'v' ) /* eg. -vvv */
1320                         {
1321                             i_verbose++;
1322                             while( *optarg == 'v' )
1323                             {
1324                                 i_verbose++;
1325                                 optarg++;
1326                             }
1327                         }
1328                         else
1329                         {
1330                             i_verbose += atoi( optarg ); /* eg. -v2 */
1331                         }
1332                     }
1333                     else
1334                     {
1335                         i_verbose++; /* -v */
1336                     }
1337                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1338                                            i_verbose );
1339                 }
1340                 else
1341                 {
1342                     config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1343                                            atoi(optarg) );
1344                 }
1345                 break;
1346             case CONFIG_ITEM_BOOL:
1347                 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
1348                 break;
1349             }
1350
1351             continue;
1352         }
1353
1354         /* Internal error: unknown option */
1355         if( !b_ignore_errors )
1356         {
1357             fprintf( stderr, "%s: unknown option ",
1358                              p_this->p_vlc->psz_object_name );
1359             if( optopt )
1360             {
1361                 fprintf( stderr, "`-%c'\n", optopt );
1362             }
1363             else
1364             {
1365                 fprintf( stderr, "`%s'\n", ppsz_argv[optind-1] );
1366             }
1367             fprintf( stderr, "Try `%s --help' for more information.\n",
1368                              p_this->p_vlc->psz_object_name );
1369
1370             free( p_longopts );
1371             free( psz_shortopts );
1372             return -1;
1373         }
1374     }
1375
1376     /* Free allocated resources */
1377     for( i_index = 0; p_longopts[i_index].name; i_index++ )
1378         free( (char *)p_longopts[i_index].name );
1379     free( p_longopts );
1380     free( psz_shortopts );
1381     if( b_ignore_errors ) free( ppsz_argv );
1382
1383     return 0;
1384 }
1385
1386 /*****************************************************************************
1387  * config_GetHomeDir: find the user's home directory.
1388  *****************************************************************************
1389  * This function will try by different ways to find the user's home path.
1390  * Note that this function is not reentrant, it should be called only once
1391  * at the beginning of main where the result will be stored for later use.
1392  *****************************************************************************/
1393 char *config_GetHomeDir( void )
1394 {
1395     char *p_tmp, *p_homedir = NULL;
1396
1397 #if defined(HAVE_GETPWUID)
1398     struct passwd *p_pw = NULL;
1399 #endif
1400
1401 #if defined(WIN32) || defined(UNDER_CE)
1402     typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
1403                                                LPTSTR );
1404 #   define CSIDL_FLAG_CREATE 0x8000
1405 #   define CSIDL_APPDATA 0x1A
1406 #   define SHGFP_TYPE_CURRENT 0
1407
1408     HINSTANCE shfolder_dll;
1409     SHGETFOLDERPATH SHGetFolderPath ;
1410
1411     /* load the shfolder dll to retrieve SHGetFolderPath */
1412     if( ( shfolder_dll = LoadLibrary("shfolder.dll") ) != NULL )
1413     {
1414         SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
1415                                                   "SHGetFolderPathA" );
1416         if ( SHGetFolderPath != NULL )
1417         {
1418             p_homedir = (char *)malloc( MAX_PATH );
1419             if( !p_homedir )
1420             {
1421                 return NULL;
1422             }
1423
1424             /* get the "Application Data" folder for the current user */
1425             if( S_OK == SHGetFolderPath( NULL,
1426                                          CSIDL_APPDATA | CSIDL_FLAG_CREATE,
1427                                          NULL, SHGFP_TYPE_CURRENT,
1428                                          p_homedir ) )
1429             {
1430                 FreeLibrary( shfolder_dll );
1431                 return p_homedir;
1432             }
1433             free( p_homedir );
1434         }
1435         FreeLibrary( shfolder_dll );
1436     }
1437 #endif
1438
1439 #if defined(HAVE_GETPWUID)
1440     if( ( p_pw = getpwuid( getuid() ) ) == NULL )
1441 #endif
1442     {
1443         if( ( p_tmp = getenv( "HOME" ) ) == NULL )
1444         {
1445             if( ( p_tmp = getenv( "TMP" ) ) == NULL )
1446             {
1447                 p_tmp = "/tmp";
1448             }
1449         }
1450
1451         p_homedir = strdup( p_tmp );
1452     }
1453 #if defined(HAVE_GETPWUID)
1454     else
1455     {
1456         p_homedir = strdup( p_pw->pw_dir );
1457     }
1458 #endif
1459
1460     return p_homedir;
1461 }