1 /*****************************************************************************
2 * configuration.c management of the modules configuration
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: configuration.c,v 1.64 2003/08/23 14:38:50 lool Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
27 #include <stdio.h> /* sprintf() */
28 #include <stdlib.h> /* free(), strtol() */
29 #include <string.h> /* strdup() */
31 # include <errno.h> /* errno */
35 # include <unistd.h> /* getuid() */
38 #ifdef HAVE_GETOPT_LONG
40 # include <getopt.h> /* getopt() */
43 # include "../extras/getopt.h"
46 #if defined(HAVE_GETPWUID)
47 # include <pwd.h> /* getpwuid() */
50 #if defined( HAVE_SYS_STAT_H )
51 # include <sys/stat.h>
53 #if defined( HAVE_SYS_TYPES_H )
54 # include <sys/types.h>
56 #if defined( WIN32 ) && !defined( UNDER_CE )
61 static int ConfigStringToKey( char * );
62 static char *ConfigKeyToString( int );
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
)
72 module_config_t
*p_config
;
75 p_config
= config_FindConfig( p_this
, psz_name
);
83 switch( p_config
->i_type
)
85 case CONFIG_ITEM_BOOL
:
86 i_type
= VLC_VAR_BOOL
;
89 case CONFIG_ITEM_INTEGER
:
90 i_type
= VLC_VAR_INTEGER
;
93 case CONFIG_ITEM_FLOAT
:
94 i_type
= VLC_VAR_FLOAT
;
97 case CONFIG_ITEM_MODULE
:
98 case CONFIG_ITEM_STRING
:
99 i_type
= VLC_VAR_STRING
;
102 case CONFIG_ITEM_FILE
:
103 i_type
= VLC_VAR_FILE
;
106 case CONFIG_ITEM_DIRECTORY
:
107 i_type
= VLC_VAR_DIRECTORY
;
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
124 *****************************************************************************/
125 int __config_GetInt( vlc_object_t
*p_this
, const char *psz_name
)
127 module_config_t
*p_config
;
129 p_config
= config_FindConfig( p_this
, psz_name
);
134 msg_Err( p_this
, "option %s does not exist", psz_name
);
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
) )
141 msg_Err( p_this
, "option %s does not refer to an int", psz_name
);
145 return p_config
->i_value
;
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
)
156 module_config_t
*p_config
;
158 p_config
= config_FindConfig( p_this
, psz_name
);
163 msg_Err( p_this
, "option %s does not exist", psz_name
);
166 if( p_config
->i_type
!= CONFIG_ITEM_FLOAT
)
168 msg_Err( p_this
, "option %s does not refer to a float", psz_name
);
172 return p_config
->f_value
;
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).
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
)
188 module_config_t
*p_config
;
189 char *psz_value
= NULL
;
191 p_config
= config_FindConfig( p_this
, psz_name
);
196 msg_Err( p_this
, "option %s does not exist", psz_name
);
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
) )
204 msg_Err( p_this
, "option %s does not refer to a string", psz_name
);
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
);
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
)
226 module_config_t
*p_config
;
227 vlc_value_t oldval
, val
;
229 p_config
= config_FindConfig( p_this
, psz_name
);
234 msg_Warn( p_this
, "option %s does not exist", psz_name
);
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
) )
242 msg_Err( p_this
, "option %s does not refer to a string", psz_name
);
246 vlc_mutex_lock( p_config
->p_lock
);
248 /* backup old value */
249 oldval
.psz_string
= p_config
->psz_value
;
251 if( psz_value
&& *psz_value
) p_config
->psz_value
= strdup( psz_value
);
252 else p_config
->psz_value
= NULL
;
254 val
.psz_string
= p_config
->psz_value
;
256 vlc_mutex_unlock( p_config
->p_lock
);
258 if( p_config
->pf_callback
)
260 p_config
->pf_callback( p_this
, psz_name
, oldval
, val
,
261 p_config
->p_callback_data
);
264 /* free old string */
265 if( oldval
.psz_string
) free( oldval
.psz_string
);
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
274 *****************************************************************************/
275 void __config_PutInt( vlc_object_t
*p_this
, const char *psz_name
, int i_value
)
277 module_config_t
*p_config
;
278 vlc_value_t oldval
, val
;
280 p_config
= config_FindConfig( p_this
, psz_name
);
285 msg_Warn( p_this
, "option %s does not exist", psz_name
);
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
) )
292 msg_Err( p_this
, "option %s does not refer to an int", psz_name
);
296 /* backup old value */
297 oldval
.i_int
= p_config
->i_value
;
299 /* if i_min == i_max == 0, then do not use them */
300 if ((p_config
->i_min
== 0) && (p_config
->i_max
== 0))
302 p_config
->i_value
= i_value
;
304 else if (i_value
< p_config
->i_min
)
306 p_config
->i_value
= p_config
->i_min
;
308 else if (i_value
> p_config
->i_max
)
310 p_config
->i_value
= p_config
->i_max
;
314 p_config
->i_value
= i_value
;
317 val
.i_int
= p_config
->i_value
;
319 if( p_config
->pf_callback
)
321 p_config
->pf_callback( p_this
, psz_name
, oldval
, val
,
322 p_config
->p_callback_data
);
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
)
335 module_config_t
*p_config
;
336 vlc_value_t oldval
, val
;
338 p_config
= config_FindConfig( p_this
, psz_name
);
343 msg_Warn( p_this
, "option %s does not exist", psz_name
);
346 if( p_config
->i_type
!= CONFIG_ITEM_FLOAT
)
348 msg_Err( p_this
, "option %s does not refer to a float", psz_name
);
352 /* backup old value */
353 oldval
.f_float
= p_config
->f_value
;
355 /* if f_min == f_max == 0, then do not use them */
356 if ((p_config
->f_min
== 0) && (p_config
->f_max
== 0))
358 p_config
->f_value
= f_value
;
360 else if (f_value
< p_config
->f_min
)
362 p_config
->f_value
= p_config
->f_min
;
364 else if (f_value
> p_config
->f_max
)
366 p_config
->f_value
= p_config
->f_max
;
370 p_config
->f_value
= f_value
;
373 val
.f_float
= p_config
->f_value
;
375 if( p_config
->pf_callback
)
377 p_config
->pf_callback( p_this
, psz_name
, oldval
, val
,
378 p_config
->p_callback_data
);
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
)
392 module_config_t
*p_item
;
395 if( !psz_name
) return NULL
;
397 p_list
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
399 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
401 p_parser
= (module_t
*)p_list
->p_values
[i_index
].p_object
;
403 if( !p_parser
->i_config_items
)
406 for( p_item
= p_parser
->p_config
;
407 p_item
->i_type
!= CONFIG_HINT_END
;
410 if( p_item
->i_type
& CONFIG_HINT
)
413 if( !strcmp( psz_name
, p_item
->psz_name
) )
415 vlc_list_release( p_list
);
421 vlc_list_release( p_list
);
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
)
435 int i
, j
, i_lines
= 1;
436 module_config_t
*p_item
;
438 /* Calculate the structure length */
439 p_module
->i_config_items
= 0;
440 p_module
->i_bool_items
= 0;
442 for( p_item
= p_orig
; p_item
->i_type
!= CONFIG_HINT_END
; p_item
++ )
446 if( p_item
->i_type
& CONFIG_ITEM
)
448 p_module
->i_config_items
++;
451 if( p_item
->i_type
== CONFIG_ITEM_BOOL
)
453 p_module
->i_bool_items
++;
457 /* Allocate memory */
458 p_module
->p_config
= (module_config_t
*)malloc( sizeof(module_config_t
)
460 if( p_module
->p_config
== NULL
)
462 msg_Err( p_module
, "config error: can't duplicate p_config" );
466 /* Do the duplication job */
467 for( i
= 0; i
< i_lines
; i
++ )
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
;
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
;
495 p_module
->p_config
[i
].p_lock
= &p_module
->object_lock
;
497 /* duplicate the string list */
498 p_module
->p_config
[i
].ppsz_list
= NULL
;
499 if( p_orig
[i
].ppsz_list
)
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
)
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
] );
509 p_module
->p_config
[i
].ppsz_list
[j
] = NULL
;
512 p_module
->p_config
[i
].pf_callback
= p_orig
[i
].pf_callback
;
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
)
523 module_config_t
*p_item
= p_module
->p_config
;
531 for( ; p_item
->i_type
!= CONFIG_HINT_END
; p_item
++ )
533 if( p_item
->psz_type
)
534 free( p_item
->psz_type
);
536 if( p_item
->psz_name
)
537 free( p_item
->psz_name
);
539 if( p_item
->psz_text
)
540 free( p_item
->psz_text
);
542 if( p_item
->psz_longtext
)
543 free( p_item
->psz_longtext
);
545 if( p_item
->psz_value
)
546 free( p_item
->psz_value
);
548 if( p_item
->psz_value_orig
)
549 free( p_item
->psz_value_orig
);
551 if( p_item
->ppsz_list
)
553 for( i
= 0; p_item
->ppsz_list
[i
]; i
++ )
554 free(p_item
->ppsz_list
[i
]);
555 free( p_item
->ppsz_list
);
559 free( p_module
->p_config
);
560 p_module
->p_config
= NULL
;
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
)
572 while( p_new
->i_type
!= CONFIG_HINT_END
)
574 p_new
->pf_callback
= p_orig
->pf_callback
;
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
)
587 while( p_new
->i_type
!= CONFIG_HINT_END
)
589 p_new
->pf_callback
= NULL
;
594 /*****************************************************************************
595 * config_ResetAll: reset the configuration data for all the modules.
596 *****************************************************************************/
597 void __config_ResetAll( vlc_object_t
*p_this
)
603 /* Acquire config file lock */
604 vlc_mutex_lock( &p_this
->p_vlc
->config_lock
);
606 p_list
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
608 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
610 p_module
= (module_t
*)p_list
->p_values
[i_index
].p_object
;
611 if( p_module
->b_submodule
) continue;
613 for( i
= 0; p_module
->p_config
[i
].i_type
!= CONFIG_HINT_END
; i
++ )
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
;
625 vlc_list_release( p_list
);
626 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
629 /*****************************************************************************
630 * config_LoadConfigFile: loads the configuration file.
631 *****************************************************************************
632 * This function is called to load the config options stored in the config
634 *****************************************************************************/
635 int __config_LoadConfigFile( vlc_object_t
*p_this
, const char *psz_module_name
)
639 module_config_t
*p_item
;
642 char *p_index
, *psz_option_name
, *psz_option_value
;
643 char *psz_filename
, *psz_homedir
;
646 psz_homedir
= p_this
->p_vlc
->psz_homedir
;
649 msg_Err( p_this
, "psz_homedir is null" );
652 psz_filename
= (char *)malloc( strlen("/" CONFIG_DIR
"/" CONFIG_FILE
) +
653 strlen(psz_homedir
) + 1 );
656 msg_Err( p_this
, "out of memory" );
659 sprintf( psz_filename
, "%s/" CONFIG_DIR
"/" CONFIG_FILE
, psz_homedir
);
661 msg_Dbg( p_this
, "opening config file %s", psz_filename
);
663 /* Acquire config file lock */
664 vlc_mutex_lock( &p_this
->p_vlc
->config_lock
);
666 file
= fopen( psz_filename
, "rt" );
669 msg_Warn( p_this
, "config file %s does not exist yet", psz_filename
);
670 free( psz_filename
);
671 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
675 /* Look for the selected module, if NULL then save everything */
676 p_list
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
678 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
680 p_parser
= (module_t
*)p_list
->p_values
[i_index
].p_object
;
683 && strcmp( psz_module_name
, p_parser
->psz_object_name
) )
688 /* The config file is organized in sections, one per module. Look for
689 * the interesting section ( a section is of the form [foo] ) */
690 fseek( file
, 0L, SEEK_SET
);
691 while( fgets( line
, 1024, file
) )
694 && (p_index
= strchr(line
,']'))
695 && (p_index
- &line
[1]
696 == (int)strlen(p_parser
->psz_object_name
))
697 && !memcmp( &line
[1], p_parser
->psz_object_name
,
698 strlen(p_parser
->psz_object_name
) ) )
701 msg_Dbg( p_this
, "loading config for module \"%s\"",
702 p_parser
->psz_object_name
);
708 /* either we found the section or we're at the EOF */
710 /* Now try to load the options in this section */
711 while( fgets( line
, 1024, file
) )
713 if( line
[0] == '[' ) break; /* end of section */
715 /* ignore comments or empty lines */
716 if( (line
[0] == '#') || (line
[0] == '\n') || (line
[0] == (char)0) )
719 /* get rid of line feed */
720 if( line
[strlen(line
)-1] == '\n' )
721 line
[strlen(line
)-1] = (char)0;
723 /* look for option name */
724 psz_option_name
= line
;
725 psz_option_value
= NULL
;
726 p_index
= strchr( line
, '=' );
727 if( !p_index
) break; /* this ain't an option!!! */
730 psz_option_value
= p_index
+ 1;
732 if( !p_parser
->i_config_items
)
737 /* try to match this option with one of the module's options */
738 for( p_item
= p_parser
->p_config
;
739 p_item
->i_type
!= CONFIG_HINT_END
;
742 if( p_item
->i_type
& CONFIG_HINT
)
746 if( !strcmp( p_item
->psz_name
, psz_option_name
) )
749 switch( p_item
->i_type
)
751 case CONFIG_ITEM_BOOL
:
752 case CONFIG_ITEM_INTEGER
:
753 if( !*psz_option_value
)
754 break; /* ignore empty option */
755 p_item
->i_value
= atoi( psz_option_value
);
757 msg_Dbg( p_this
, "option \"%s\", value %i",
758 p_item
->psz_name
, p_item
->i_value
);
762 case CONFIG_ITEM_FLOAT
:
763 if( !*psz_option_value
)
764 break; /* ignore empty option */
765 p_item
->f_value
= (float)atof( psz_option_value
);
767 msg_Dbg( p_this
, "option \"%s\", value %f",
768 p_item
->psz_name
, (double)p_item
->f_value
);
771 case CONFIG_ITEM_KEY
:
772 if( !*psz_option_value
)
773 break; /* ignore empty option */
774 p_item
->i_value
= ConfigStringToKey( psz_option_value
);
778 vlc_mutex_lock( p_item
->p_lock
);
780 /* free old string */
781 if( p_item
->psz_value
)
782 free( p_item
->psz_value
);
784 p_item
->psz_value
= *psz_option_value
?
785 strdup( psz_option_value
) : NULL
;
787 vlc_mutex_unlock( p_item
->p_lock
);
790 msg_Dbg( p_this
, "option \"%s\", value \"%s\"",
792 p_item
->psz_value
? p_item
->psz_value
: "" );
802 vlc_list_release( p_list
);
805 free( psz_filename
);
807 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
812 /*****************************************************************************
813 * config_SaveConfigFile: Save a module's config options.
814 *****************************************************************************
815 * This will save the specified module's config options to the config file.
816 * If psz_module_name is NULL then we save all the modules config options.
817 * It's no use to save the config options that kept their default values, so
818 * we'll try to be a bit clever here.
820 * When we save we mustn't delete the config options of the modules that
821 * haven't been loaded. So we cannot just create a new config file with the
822 * config structures we've got in memory.
823 * I don't really know how to deal with this nicely, so I will use a completly
825 * I will load the config file in memory, but skipping all the sections of the
826 * modules we want to save. Then I will create a brand new file, dump the file
827 * loaded in memory and then append the sections of the modules we want to
830 *****************************************************************************/
831 int __config_SaveConfigFile( vlc_object_t
*p_this
, const char *psz_module_name
)
835 module_config_t
*p_item
;
837 char p_line
[1024], *p_index2
;
839 char *p_bigbuffer
, *p_index
;
841 char *psz_filename
, *psz_homedir
;
844 /* Acquire config file lock */
845 vlc_mutex_lock( &p_this
->p_vlc
->config_lock
);
847 psz_homedir
= p_this
->p_vlc
->psz_homedir
;
850 msg_Err( p_this
, "psz_homedir is null" );
851 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
854 psz_filename
= (char *)malloc( strlen("/" CONFIG_DIR
"/" CONFIG_FILE
) +
855 strlen(psz_homedir
) + 1 );
858 msg_Err( p_this
, "out of memory" );
859 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
862 sprintf( psz_filename
, "%s/" CONFIG_DIR
, psz_homedir
);
864 #if defined( UNDER_CE )
866 wchar_t psz_new
[ MAX_PATH
];
867 MultiByteToWideChar( CP_ACP
, 0, psz_filename
, -1, psz_new
, MAX_PATH
);
868 if( CreateDirectory( psz_new
, NULL
) )
870 msg_Err( p_this
, "could not create %s", psz_filename
);
874 #elif defined( HAVE_ERRNO_H )
875 # if defined( WIN32 )
876 if( mkdir( psz_filename
) && errno
!= EEXIST
)
878 if( mkdir( psz_filename
, 0755 ) && errno
!= EEXIST
)
881 msg_Err( p_this
, "could not create %s (%s)",
882 psz_filename
, strerror(errno
) );
886 if( mkdir( psz_filename
) )
888 msg_Err( p_this
, "could not create %s", psz_filename
);
893 strcat( psz_filename
, "/" CONFIG_FILE
);
896 msg_Dbg( p_this
, "opening config file %s", psz_filename
);
898 file
= fopen( psz_filename
, "rt" );
901 msg_Warn( p_this
, "config file %s does not exist yet", psz_filename
);
905 /* look for file size */
906 fseek( file
, 0L, SEEK_END
);
907 i_sizebuf
= ftell( file
);
908 fseek( file
, 0L, SEEK_SET
);
911 p_bigbuffer
= p_index
= malloc( i_sizebuf
+1 );
914 msg_Err( p_this
, "out of memory" );
915 if( file
) fclose( file
);
916 free( psz_filename
);
917 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
922 /* List all available modules */
923 p_list
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
925 /* backup file into memory, we only need to backup the sections we won't
928 while( file
&& fgets( p_line
, 1024, file
) )
930 if( (p_line
[0] == '[') && (p_index2
= strchr(p_line
,']')))
933 /* we found a section, check if we need to do a backup */
934 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
936 p_parser
= (module_t
*)p_list
->p_values
[i_index
].p_object
;
938 if( ((p_index2
- &p_line
[1])
939 == (int)strlen(p_parser
->psz_object_name
) )
940 && !memcmp( &p_line
[1], p_parser
->psz_object_name
,
941 strlen(p_parser
->psz_object_name
) ) )
943 if( !psz_module_name
)
945 else if( !strcmp( psz_module_name
,
946 p_parser
->psz_object_name
) )
951 if( i_index
== p_list
->i_count
)
953 /* we don't have this section in our list so we need to back
956 msg_Dbg( p_this
, "backing up config for unknown module \"%s\"",
968 /* save line if requested and line is valid (doesn't begin with a
969 * space, tab, or eol) */
970 if( b_backup
&& (p_line
[0] != '\n') && (p_line
[0] != ' ')
971 && (p_line
[0] != '\t') )
973 strcpy( p_index
, p_line
);
974 p_index
+= strlen( p_line
);
977 if( file
) fclose( file
);
981 * Save module config in file
984 file
= fopen( psz_filename
, "wt" );
987 msg_Warn( p_this
, "could not open config file %s for writing",
989 free( psz_filename
);
990 vlc_list_release( p_list
);
991 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
995 fprintf( file
, "###\n### " COPYRIGHT_MESSAGE
"\n###\n\n" );
997 /* Look for the selected module, if NULL then save everything */
998 for( i_index
= 0; i_index
< p_list
->i_count
; i_index
++ )
1000 p_parser
= (module_t
*)p_list
->p_values
[i_index
].p_object
;
1002 if( psz_module_name
&& strcmp( psz_module_name
,
1003 p_parser
->psz_object_name
) )
1006 if( !p_parser
->i_config_items
)
1009 msg_Dbg( p_this
, "saving config for module \"%s\"",
1010 p_parser
->psz_object_name
);
1012 fprintf( file
, "[%s]", p_parser
->psz_object_name
);
1013 if( p_parser
->psz_longname
)
1014 fprintf( file
, " # %s\n\n", p_parser
->psz_longname
);
1016 fprintf( file
, "\n\n" );
1018 for( p_item
= p_parser
->p_config
;
1019 p_item
->i_type
!= CONFIG_HINT_END
;
1023 if( p_item
->i_type
& CONFIG_HINT
)
1027 switch( p_item
->i_type
)
1029 case CONFIG_ITEM_BOOL
:
1030 case CONFIG_ITEM_INTEGER
:
1031 if( p_item
->psz_text
)
1032 fprintf( file
, "# %s (%s)\n", p_item
->psz_text
,
1033 (p_item
->i_type
== CONFIG_ITEM_BOOL
) ?
1034 _("boolean") : _("integer") );
1035 if( p_item
->i_value
== p_item
->i_value_orig
)
1036 fprintf( file
, "#" );
1037 fprintf( file
, "%s=%i\n", p_item
->psz_name
, p_item
->i_value
);
1039 case CONFIG_ITEM_KEY
:
1040 if( p_item
->psz_text
)
1041 fprintf( file
, "# %s (%s)\n", p_item
->psz_text
,
1043 psz_key
= ConfigKeyToString( p_item
->i_value
);
1044 fprintf( file
, "%s=%s\n", p_item
->psz_name
,
1045 psz_key
? psz_key
: "" );
1046 if ( psz_key
) free( psz_key
);
1049 case CONFIG_ITEM_FLOAT
:
1050 if( p_item
->psz_text
)
1051 fprintf( file
, "# %s (%s)\n", p_item
->psz_text
,
1053 if( p_item
->f_value
== p_item
->f_value_orig
)
1054 fprintf( file
, "#" );
1055 fprintf( file
, "%s=%f\n", p_item
->psz_name
,
1056 (double)p_item
->f_value
);
1060 if( p_item
->psz_text
)
1061 fprintf( file
, "# %s (%s)\n", p_item
->psz_text
,
1063 if( (!p_item
->psz_value
&& !p_item
->psz_value_orig
) ||
1064 (p_item
->psz_value
&& p_item
->psz_value_orig
&&
1065 !strcmp( p_item
->psz_value
, p_item
->psz_value_orig
)) )
1066 fprintf( file
, "#" );
1067 fprintf( file
, "%s=%s\n", p_item
->psz_name
,
1068 p_item
->psz_value
? p_item
->psz_value
: "" );
1072 fprintf( file
, "\n" );
1075 vlc_list_release( p_list
);
1078 * Restore old settings from the config in file
1080 fputs( p_bigbuffer
, file
);
1081 free( p_bigbuffer
);
1084 free( psz_filename
);
1085 vlc_mutex_unlock( &p_this
->p_vlc
->config_lock
);
1090 /*****************************************************************************
1091 * config_LoadCmdLine: parse command line
1092 *****************************************************************************
1093 * Parse command line for configuration options.
1094 * Now that the module_bank has been initialized, we can dynamically
1095 * generate the longopts structure used by getops. We have to do it this way
1096 * because we don't know (and don't want to know) in advance the configuration
1097 * options used (ie. exported) by each module.
1098 *****************************************************************************/
1099 int __config_LoadCmdLine( vlc_object_t
*p_this
, int *pi_argc
, char *ppsz_argv
[],
1100 vlc_bool_t b_ignore_errors
)
1102 int i_cmd
, i_index
, i_opts
, i_shortopts
, flag
, i_verbose
= 0;
1105 module_config_t
*p_item
;
1106 struct option
*p_longopts
;
1107 int i_modules_index
;
1110 module_config_t
*pp_shortopts
[256];
1111 char *psz_shortopts
;
1113 /* Set default configuration and copy arguments */
1114 p_this
->p_vlc
->i_argc
= *pi_argc
;
1115 p_this
->p_vlc
->ppsz_argv
= ppsz_argv
;
1117 p_this
->p_vlc
->p_channel
= NULL
;
1120 /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
1121 * is the PSN - process serial number (a unique PID-ish thingie)
1122 * still ok for real Darwin & when run from command line */
1123 if ( (*pi_argc
> 1) && (strncmp( ppsz_argv
[ 1 ] , "-psn" , 4 ) == 0) )
1124 /* for example -psn_0_9306113 */
1126 /* GDMF!... I can't do this or else the MacOSX window server will
1127 * not pick up the PSN and not register the app and we crash...
1128 * hence the following kludge otherwise we'll get confused w/ argv[1]
1129 * being an input file name */
1131 ppsz_argv
[ 1 ] = NULL
;
1133 *pi_argc
= *pi_argc
- 1;
1139 /* List all modules */
1140 p_list
= vlc_list_find( p_this
, VLC_OBJECT_MODULE
, FIND_ANYWHERE
);
1143 * Generate the longopts and shortopts structures used by getopt_long
1147 for( i_modules_index
= 0; i_modules_index
< p_list
->i_count
;
1150 p_parser
= (module_t
*)p_list
->p_values
[i_modules_index
].p_object
;
1152 /* count the number of exported configuration options (to allocate
1153 * longopts). We also need to allocate space for too options when
1154 * dealing with boolean to allow for --foo and --no-foo */
1155 i_opts
+= p_parser
->i_config_items
1156 + 2 * p_parser
->i_bool_items
;
1159 p_longopts
= malloc( sizeof(struct option
) * (i_opts
+ 1) );
1160 if( p_longopts
== NULL
)
1162 msg_Err( p_this
, "out of memory" );
1163 vlc_list_release( p_list
);
1167 psz_shortopts
= malloc( sizeof( char ) * (2 * i_opts
+ 1) );
1168 if( psz_shortopts
== NULL
)
1170 msg_Err( p_this
, "out of memory" );
1172 vlc_list_release( p_list
);
1176 /* If we are requested to ignore errors, then we must work on a copy
1177 * of the ppsz_argv array, otherwise getopt_long will reorder it for
1178 * us, ignoring the arity of the options */
1179 if( b_ignore_errors
)
1181 ppsz_argv
= (char**)malloc( *pi_argc
* sizeof(char *) );
1182 if( ppsz_argv
== NULL
)
1184 msg_Err( p_this
, "out of memory" );
1185 free( psz_shortopts
);
1187 vlc_list_release( p_list
);
1190 memcpy( ppsz_argv
, p_this
->p_vlc
->ppsz_argv
,
1191 *pi_argc
* sizeof(char *) );
1195 for( i_index
= 0; i_index
< 256; i_index
++ )
1197 pp_shortopts
[i_index
] = NULL
;
1200 /* Fill the p_longopts and psz_shortopts structures */
1202 for( i_modules_index
= 0; i_modules_index
< p_list
->i_count
;
1205 p_parser
= (module_t
*)p_list
->p_values
[i_modules_index
].p_object
;
1207 if( !p_parser
->i_config_items
)
1210 for( p_item
= p_parser
->p_config
;
1211 p_item
->i_type
!= CONFIG_HINT_END
;
1215 if( p_item
->i_type
& CONFIG_HINT
)
1218 /* Add item to long options */
1219 p_longopts
[i_index
].name
= strdup( p_item
->psz_name
);
1220 if( p_longopts
[i_index
].name
== NULL
) continue;
1221 p_longopts
[i_index
].has_arg
=
1222 (p_item
->i_type
== CONFIG_ITEM_BOOL
)?
1223 no_argument
: required_argument
;
1224 p_longopts
[i_index
].flag
= &flag
;
1225 p_longopts
[i_index
].val
= 0;
1228 /* When dealing with bools we also need to add the --no-foo
1230 if( p_item
->i_type
== CONFIG_ITEM_BOOL
)
1232 char *psz_name
= malloc( strlen(p_item
->psz_name
) + 3 );
1233 if( psz_name
== NULL
) continue;
1234 strcpy( psz_name
, "no" );
1235 strcat( psz_name
, p_item
->psz_name
);
1237 p_longopts
[i_index
].name
= psz_name
;
1238 p_longopts
[i_index
].has_arg
= no_argument
;
1239 p_longopts
[i_index
].flag
= &flag
;
1240 p_longopts
[i_index
].val
= 1;
1243 psz_name
= malloc( strlen(p_item
->psz_name
) + 4 );
1244 if( psz_name
== NULL
) continue;
1245 strcpy( psz_name
, "no-" );
1246 strcat( psz_name
, p_item
->psz_name
);
1248 p_longopts
[i_index
].name
= psz_name
;
1249 p_longopts
[i_index
].has_arg
= no_argument
;
1250 p_longopts
[i_index
].flag
= &flag
;
1251 p_longopts
[i_index
].val
= 1;
1255 /* If item also has a short option, add it */
1256 if( p_item
->i_short
)
1258 pp_shortopts
[(int)p_item
->i_short
] = p_item
;
1259 psz_shortopts
[i_shortopts
] = p_item
->i_short
;
1261 if( p_item
->i_type
!= CONFIG_ITEM_BOOL
)
1263 psz_shortopts
[i_shortopts
] = ':';
1266 if( p_item
->i_short
== 'v' )
1268 psz_shortopts
[i_shortopts
] = ':';
1276 /* We don't need the module list anymore */
1277 vlc_list_release( p_list
);
1279 /* Close the longopts and shortopts structures */
1280 memset( &p_longopts
[i_index
], 0, sizeof(struct option
) );
1281 psz_shortopts
[i_shortopts
] = '\0';
1284 * Parse the command line options
1288 while( ( i_cmd
= getopt_long( *pi_argc
, ppsz_argv
, psz_shortopts
,
1289 p_longopts
, &i_index
) ) != EOF
)
1291 /* A long option has been recognized */
1294 module_config_t
*p_conf
;
1295 char *psz_name
= (char *)p_longopts
[i_index
].name
;
1297 /* Check if we deal with a --nofoo or --no-foo long option */
1298 if( flag
) psz_name
+= psz_name
[2] == '-' ? 3 : 2;
1300 /* Store the configuration option */
1301 p_conf
= config_FindConfig( p_this
, psz_name
);
1303 if( p_conf
) switch( p_conf
->i_type
)
1305 case CONFIG_ITEM_STRING
:
1306 case CONFIG_ITEM_FILE
:
1307 case CONFIG_ITEM_DIRECTORY
:
1308 case CONFIG_ITEM_MODULE
:
1309 config_PutPsz( p_this
, psz_name
, optarg
);
1311 case CONFIG_ITEM_INTEGER
:
1312 config_PutInt( p_this
, psz_name
, atoi(optarg
));
1314 case CONFIG_ITEM_FLOAT
:
1315 config_PutFloat( p_this
, psz_name
, (float)atof(optarg
) );
1317 case CONFIG_ITEM_KEY
:
1318 config_PutInt( p_this
, psz_name
, ConfigStringToKey( optarg
) );
1320 case CONFIG_ITEM_BOOL
:
1321 config_PutInt( p_this
, psz_name
, !flag
);
1328 /* A short option has been recognized */
1329 if( pp_shortopts
[i_cmd
] != NULL
)
1331 switch( pp_shortopts
[i_cmd
]->i_type
)
1333 case CONFIG_ITEM_STRING
:
1334 case CONFIG_ITEM_FILE
:
1335 case CONFIG_ITEM_DIRECTORY
:
1336 case CONFIG_ITEM_MODULE
:
1337 config_PutPsz( p_this
, pp_shortopts
[i_cmd
]->psz_name
, optarg
);
1339 case CONFIG_ITEM_INTEGER
:
1344 if( *optarg
== 'v' ) /* eg. -vvv */
1347 while( *optarg
== 'v' )
1355 i_verbose
+= atoi( optarg
); /* eg. -v2 */
1360 i_verbose
++; /* -v */
1362 config_PutInt( p_this
, pp_shortopts
[i_cmd
]->psz_name
,
1367 config_PutInt( p_this
, pp_shortopts
[i_cmd
]->psz_name
,
1371 case CONFIG_ITEM_BOOL
:
1372 config_PutInt( p_this
, pp_shortopts
[i_cmd
]->psz_name
, 1 );
1379 /* Internal error: unknown option */
1380 if( !b_ignore_errors
)
1382 fprintf( stderr
, "%s: unknown option ",
1383 p_this
->p_vlc
->psz_object_name
);
1386 fprintf( stderr
, "`-%c'\n", optopt
);
1390 fprintf( stderr
, "`%s'\n", ppsz_argv
[optind
-1] );
1392 fprintf( stderr
, "Try `%s --help' for more information.\n",
1393 p_this
->p_vlc
->psz_object_name
);
1396 free( psz_shortopts
);
1401 /* Free allocated resources */
1402 for( i_index
= 0; p_longopts
[i_index
].name
; i_index
++ )
1403 free( (char *)p_longopts
[i_index
].name
);
1405 free( psz_shortopts
);
1406 if( b_ignore_errors
) free( ppsz_argv
);
1411 /*****************************************************************************
1412 * config_GetHomeDir: find the user's home directory.
1413 *****************************************************************************
1414 * This function will try by different ways to find the user's home path.
1415 * Note that this function is not reentrant, it should be called only once
1416 * at the beginning of main where the result will be stored for later use.
1417 *****************************************************************************/
1418 char *config_GetHomeDir( void )
1420 char *p_tmp
, *p_homedir
= NULL
;
1422 #if defined(HAVE_GETPWUID)
1423 struct passwd
*p_pw
= NULL
;
1426 #if defined(WIN32) || defined(UNDER_CE)
1427 typedef HRESULT (WINAPI
*SHGETFOLDERPATH
)( HWND
, int, HANDLE
, DWORD
,
1429 # define CSIDL_FLAG_CREATE 0x8000
1430 # define CSIDL_APPDATA 0x1A
1431 # define SHGFP_TYPE_CURRENT 0
1433 HINSTANCE shfolder_dll
;
1434 SHGETFOLDERPATH SHGetFolderPath
;
1436 /* load the shfolder dll to retrieve SHGetFolderPath */
1437 if( ( shfolder_dll
= LoadLibrary("shfolder.dll") ) != NULL
)
1439 SHGetFolderPath
= (void *)GetProcAddress( shfolder_dll
,
1440 "SHGetFolderPathA" );
1441 if ( SHGetFolderPath
!= NULL
)
1443 p_homedir
= (char *)malloc( MAX_PATH
);
1449 /* get the "Application Data" folder for the current user */
1450 if( S_OK
== SHGetFolderPath( NULL
,
1451 CSIDL_APPDATA
| CSIDL_FLAG_CREATE
,
1452 NULL
, SHGFP_TYPE_CURRENT
,
1455 FreeLibrary( shfolder_dll
);
1460 FreeLibrary( shfolder_dll
);
1464 #if defined(HAVE_GETPWUID)
1465 if( ( p_pw
= getpwuid( getuid() ) ) == NULL
)
1468 if( ( p_tmp
= getenv( "HOME" ) ) == NULL
)
1470 if( ( p_tmp
= getenv( "TMP" ) ) == NULL
)
1476 p_homedir
= strdup( p_tmp
);
1478 #if defined(HAVE_GETPWUID)
1481 p_homedir
= strdup( p_pw
->pw_dir
);
1490 static int ConfigStringToKey( char *psz_key
)
1494 char *psz_parser
= strchr( psz_key
, '-' );
1495 while( psz_parser
&& psz_parser
!= psz_key
)
1497 for ( i
= 0; i
< sizeof(modifiers
) / sizeof(key_descriptor_t
); i
++ )
1499 if ( !strncasecmp( modifiers
[i
].psz_key_string
, psz_key
, strlen( modifiers
[i
].psz_key_string
) ) )
1501 i_key
|= modifiers
[i
].i_key_code
;
1504 psz_key
= psz_parser
+ 1;
1505 psz_parser
= strchr( psz_key
, '-' );
1507 for ( i
= 0; i
< sizeof(keys
) / sizeof( key_descriptor_t
); i
++ )
1509 if ( !strcasecmp( keys
[i
].psz_key_string
, psz_key
) )
1511 i_key
|= keys
[i
].i_key_code
;
1519 static char *ConfigKeyToString( int i_key
)
1521 char *psz_key
= malloc( 100 );
1531 index
< (sizeof(modifiers
) / sizeof(key_descriptor_t
));
1534 if ( i_key
& modifiers
[index
].i_key_code
)
1536 p
+= sprintf( p
, "%s-", modifiers
[index
].psz_key_string
);
1540 index
< (sizeof(keys
) / sizeof( key_descriptor_t
));
1543 if ( (int)( i_key
& ~KEY_MODIFIER
) == keys
[index
].i_key_code
)
1545 p
+= sprintf( p
, "%s", keys
[index
].psz_key_string
);