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