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