1 /*****************************************************************************
2 * configuration.c management of the modules configuration
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: configuration.c,v 1.6 2002/03/17 11:12:08 gbazin 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 *****************************************************************************/
24 #include <stdio.h> /* sprintf() */
25 #include <stdlib.h> /* free(), strtol() */
26 #include <string.h> /* strdup() */
27 #include <unistd.h> /* getuid() */
29 #include <videolan/vlc.h>
31 #if defined(HAVE_GETPWUID) || defined(HAVE_GETPWUID_R)
32 #include <pwd.h> /* getpwuid() */
36 #include <sys/types.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static char *GetHomeDir( void );
43 /*****************************************************************************
44 * config_GetIntVariable: get the value of an int variable
45 *****************************************************************************
46 * This function is used to get the value of variables which are internally
47 * represented by an integer (MODULE_CONFIG_ITEM_INTEGER and
48 * MODULE_CONFIG_ITEM_BOOL).
49 *****************************************************************************/
50 int config_GetIntVariable( const char *psz_name )
52 module_config_t *p_config;
54 p_config = config_FindConfig( psz_name );
59 intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
62 if( (p_config->i_type!=MODULE_CONFIG_ITEM_INTEGER) &&
63 (p_config->i_type!=MODULE_CONFIG_ITEM_BOOL) )
65 intf_ErrMsg( "config error: option %s doesn't refer to an int",
70 return p_config->i_value;
73 /*****************************************************************************
74 * config_GetPszVariable: get the string value of a string variable
75 *****************************************************************************
76 * This function is used to get the value of variables which are internally
77 * represented by a string (MODULE_CONFIG_ITEM_STRING, MODULE_CONFIG_ITEM_FILE,
78 * and MODULE_CONFIG_ITEM_PLUGIN).
80 * Important note: remember to free() the returned char* because it a duplicate
81 * of the actual value. It isn't safe to return a pointer to the actual value
82 * as it can be modified at any time.
83 *****************************************************************************/
84 char * config_GetPszVariable( const char *psz_name )
86 module_config_t *p_config;
87 char *psz_value = NULL;
89 p_config = config_FindConfig( psz_name );
94 intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
97 if( (p_config->i_type!=MODULE_CONFIG_ITEM_STRING) &&
98 (p_config->i_type!=MODULE_CONFIG_ITEM_FILE) &&
99 (p_config->i_type!=MODULE_CONFIG_ITEM_PLUGIN) )
101 intf_ErrMsg( "config error: option %s doesn't refer to a string",
106 /* return a copy of the string */
107 vlc_mutex_lock( p_config->p_lock );
108 if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
109 vlc_mutex_unlock( p_config->p_lock );
114 /*****************************************************************************
115 * config_PutPszVariable: set the string value of a string variable
116 *****************************************************************************
117 * This function is used to set the value of variables which are internally
118 * represented by a string (MODULE_CONFIG_ITEM_STRING, MODULE_CONFIG_ITEM_FILE,
119 * and MODULE_CONFIG_ITEM_PLUGIN).
120 *****************************************************************************/
121 void config_PutPszVariable( const char *psz_name, char *psz_value )
123 module_config_t *p_config;
125 p_config = config_FindConfig( psz_name );
130 intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
133 if( (p_config->i_type!=MODULE_CONFIG_ITEM_STRING) &&
134 (p_config->i_type!=MODULE_CONFIG_ITEM_FILE) &&
135 (p_config->i_type!=MODULE_CONFIG_ITEM_PLUGIN) )
137 intf_ErrMsg( "config error: option %s doesn't refer to a string",
142 vlc_mutex_lock( p_config->p_lock );
144 /* free old string */
145 if( p_config->psz_value ) free( p_config->psz_value );
147 if( psz_value ) p_config->psz_value = strdup( psz_value );
148 else p_config->psz_value = NULL;
150 vlc_mutex_unlock( p_config->p_lock );
154 /*****************************************************************************
155 * config_PutIntVariable: set the integer value of an int variable
156 *****************************************************************************
157 * This function is used to set the value of variables which are internally
158 * represented by an integer (MODULE_CONFIG_ITEM_INTEGER and
159 * MODULE_CONFIG_ITEM_BOOL).
160 *****************************************************************************/
161 void config_PutIntVariable( const char *psz_name, int i_value )
163 module_config_t *p_config;
165 p_config = config_FindConfig( psz_name );
170 intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
173 if( (p_config->i_type!=MODULE_CONFIG_ITEM_INTEGER) &&
174 (p_config->i_type!=MODULE_CONFIG_ITEM_BOOL) )
176 intf_ErrMsg( "config error: option %s doesn't refer to an int",
181 p_config->i_value = i_value;
184 /*****************************************************************************
185 * config_FindConfig: find the config structure associated with an option.
186 *****************************************************************************
187 * FIXME: This function really needs to be optimized.
188 *****************************************************************************/
189 module_config_t *config_FindConfig( const char *psz_name )
194 if( !psz_name ) return NULL;
196 for( p_module = p_module_bank->first ;
198 p_module = p_module->next )
200 for( i = 0; i < p_module->i_config_lines; i++ )
202 if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
205 if( !strcmp( psz_name, p_module->p_config[i].psz_name ) )
206 return &p_module->p_config[i];
213 /*****************************************************************************
214 * config_Duplicate: creates a duplicate of a module's configuration data.
215 *****************************************************************************
216 * Unfortunatly we cannot work directly with the module's config data as
217 * this module might be unloaded from memory at any time (remember HideModule).
218 * This is why we need to create an exact copy of the config data.
219 *****************************************************************************/
220 module_config_t *config_Duplicate( module_t *p_module )
223 module_config_t *p_config;
225 /* allocate memory */
226 p_config = (module_config_t *)malloc( sizeof(module_config_t)
227 * p_module->i_config_lines );
228 if( p_config == NULL )
230 intf_ErrMsg( "config error: can't duplicate p_config" );
234 for( i = 0; i < p_module->i_config_lines ; i++ )
236 p_config[i].i_type = p_module->p_config_orig[i].i_type;
237 p_config[i].i_value = p_module->p_config_orig[i].i_value;
238 p_config[i].b_dirty = p_module->p_config_orig[i].b_dirty;
239 p_config[i].p_lock = &p_module->config_lock;
240 if( p_module->p_config_orig[i].psz_name )
241 p_config[i].psz_name =
242 strdup( p_module->p_config_orig[i].psz_name );
243 else p_config[i].psz_name = NULL;
244 if( p_module->p_config_orig[i].psz_text )
245 p_config[i].psz_text =
246 strdup( p_module->p_config_orig[i].psz_text );
247 else p_config[i].psz_text = NULL;
248 if( p_module->p_config_orig[i].psz_longtext )
249 p_config[i].psz_longtext =
250 strdup( p_module->p_config_orig[i].psz_longtext );
251 else p_config[i].psz_longtext = NULL;
252 if( p_module->p_config_orig[i].psz_value )
253 p_config[i].psz_value =
254 strdup( p_module->p_config_orig[i].psz_value );
255 else p_config[i].psz_value = NULL;
257 /* the callback pointer is only valid when the module is loaded so this
258 * value is set in ActivateModule() and reset in DeactivateModule() */
259 p_config[i].p_callback = NULL;
265 /*****************************************************************************
266 * config_LoadConfigFile: loads the configuration file.
267 *****************************************************************************
268 * This function is called to load the config options stored in the config
270 *****************************************************************************/
271 int config_LoadConfigFile( const char *psz_module_name )
276 char *p_index, *psz_option_name, *psz_option_value;
278 char *psz_filename, *psz_homedir;
280 /* Acquire config file lock */
281 vlc_mutex_lock( &p_main->config_lock );
283 psz_homedir = GetHomeDir();
286 intf_ErrMsg( "config error: GetHomeDir failed" );
287 vlc_mutex_unlock( &p_main->config_lock );
290 psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
291 strlen(psz_homedir) + 1 );
294 intf_ErrMsg( "config error: couldn't malloc psz_filename" );
296 vlc_mutex_unlock( &p_main->config_lock );
299 sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
302 intf_WarnMsg( 5, "config: opening config file %s", psz_filename );
304 file = fopen( psz_filename, "r" );
307 intf_WarnMsg( 1, "config: couldn't open config file %s for reading",
309 free( psz_filename );
310 vlc_mutex_unlock( &p_main->config_lock );
314 /* Look for the selected module, if NULL then save everything */
315 for( p_module = p_module_bank->first ; p_module != NULL ;
316 p_module = p_module->next )
319 if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
322 /* The config file is organized in sections, one per module. Look for
323 * the interesting section ( a section is of the form [foo] ) */
325 while( fgets( line, 1024, file ) )
327 if( (line[0] == '[') && (p_index = strchr(line,']')) &&
328 (p_index - &line[1] == strlen(p_module->psz_name) ) &&
329 !memcmp( &line[1], p_module->psz_name,
330 strlen(p_module->psz_name) ) )
332 intf_WarnMsg( 5, "config: loading config for module <%s>",
333 p_module->psz_name );
338 /* either we found the section or we're at the EOF */
340 /* Now try to load the options in this section */
341 while( fgets( line, 1024, file ) )
343 if( line[0] == '[' ) break; /* end of section */
345 /* ignore comments or empty lines */
346 if( (line[0] == '#') || (line[0] == (char)0) ) continue;
348 /* get rid of line feed */
349 if( line[strlen(line)-1] == '\n' )
350 line[strlen(line)-1] = (char)0;
352 /* look for option name */
353 psz_option_name = line;
354 psz_option_value = NULL;
355 p_index = strchr( line, '=' );
356 if( !p_index ) break; /* this ain't an option!!! */
359 psz_option_value = p_index + 1;
361 /* try to match this option with one of the module's options */
362 for( i = 0; i < p_module->i_config_lines; i++ )
364 if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
367 if( !strcmp( p_module->p_config[i].psz_name,
371 switch( p_module->p_config[i].i_type )
373 case MODULE_CONFIG_ITEM_BOOL:
374 case MODULE_CONFIG_ITEM_INTEGER:
375 p_module->p_config[i].i_value =
376 atoi( psz_option_value);
377 intf_WarnMsg( 7, "config: found <%s> option %s=%i",
379 p_module->p_config[i].psz_name,
380 p_module->p_config[i].i_value );
384 vlc_mutex_lock( p_module->p_config[i].p_lock );
386 /* free old string */
387 if( p_module->p_config[i].psz_value )
388 free( p_module->p_config[i].psz_value );
390 p_module->p_config[i].psz_value =
391 strdup( psz_option_value );
393 vlc_mutex_unlock( p_module->p_config[i].p_lock );
395 intf_WarnMsg( 7, "config: found <%s> option %s=%s",
397 p_module->p_config[i].psz_name,
398 p_module->p_config[i].psz_value );
408 free( psz_filename );
410 vlc_mutex_unlock( &p_main->config_lock );
415 /*****************************************************************************
416 * config_SaveConfigFile: Save a module's config options.
417 *****************************************************************************
418 * This will save the specified module's config options to the config file.
419 * If psz_module_name is NULL then we save all the modules config options.
420 * It's no use to save the config options that kept their default values, so
421 * we'll try to be a bit clever here.
423 * When we save we mustn't delete the config options of the plugins that
424 * haven't been loaded. So we cannot just create a new config file with the
425 * config structures we've got in memory.
426 * I don't really know how to deal with this nicely, so I will use a completly
428 * I will load the config file in memory, but skipping all the sections of the
429 * modules we want to save. Then I will create a brand new file, dump the file
430 * loaded in memory and then append the sections of the modules we want to
433 *****************************************************************************/
434 int config_SaveConfigFile( const char *psz_module_name )
438 char p_line[1024], *p_index2;
439 int i, i_sizebuf = 0;
440 char *p_bigbuffer, *p_index;
442 char *psz_filename, *psz_homedir;
444 /* Acquire config file lock */
445 vlc_mutex_lock( &p_main->config_lock );
447 psz_homedir = GetHomeDir();
450 intf_ErrMsg( "config error: GetHomeDir failed" );
451 vlc_mutex_unlock( &p_main->config_lock );
454 psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
455 strlen(psz_homedir) + 1 );
458 intf_ErrMsg( "config error: couldn't malloc psz_filename" );
460 vlc_mutex_unlock( &p_main->config_lock );
463 sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
466 mkdir( psz_filename, 0755 );
468 mkdir( psz_filename );
470 strcat( psz_filename, "/" CONFIG_FILE );
473 intf_WarnMsg( 5, "config: opening config file %s", psz_filename );
475 file = fopen( psz_filename, "r" );
478 intf_WarnMsg( 1, "config: couldn't open config file %s for reading",
483 /* look for file size */
484 fseek( file, 0, SEEK_END );
485 i_sizebuf = ftell( file );
489 p_bigbuffer = p_index = malloc( i_sizebuf+1 );
492 intf_ErrMsg( "config error: couldn't malloc bigbuffer" );
493 if( file ) fclose( file );
494 free( psz_filename );
495 vlc_mutex_unlock( &p_main->config_lock );
500 /* backup file into memory, we only need to backup the sections we won't
503 while( file && fgets( p_line, 1024, file ) )
505 if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
507 /* we found a section, check if we need to do a backup */
508 for( p_module = p_module_bank->first; p_module != NULL;
509 p_module = p_module->next )
511 if( ((p_index2 - &p_line[1]) == strlen(p_module->psz_name) ) &&
512 !memcmp( &p_line[1], p_module->psz_name,
513 strlen(p_module->psz_name) ) )
515 if( !psz_module_name )
517 else if( !strcmp( psz_module_name, p_module->psz_name ) )
524 /* we don't have this section in our list so we need to back
527 intf_WarnMsg( 5, "config: backing up config for "
528 "unknown module <%s>", &p_line[1] );
539 /* save line if requested and line is valid (doesn't begin with a
540 * space, tab, or eol) */
541 if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
542 && (p_line[0] != '\t') )
544 strcpy( p_index, p_line );
545 p_index += strlen( p_line );
548 if( file ) fclose( file );
552 * Save module config in file
555 file = fopen( psz_filename, "w" );
558 intf_WarnMsg( 1, "config: couldn't open config file %s for writing",
560 free( psz_filename );
561 vlc_mutex_unlock( &p_main->config_lock );
565 fprintf( file, "###\n### " COPYRIGHT_MESSAGE "\n###\n\n" );
567 /* Look for the selected module, if NULL then save everything */
568 for( p_module = p_module_bank->first ; p_module != NULL ;
569 p_module = p_module->next )
572 if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
575 if( !p_module->i_config_items )
578 intf_WarnMsg( 5, "config: saving config for module <%s>",
579 p_module->psz_name );
581 fprintf( file, "[%s]\n", p_module->psz_name );
583 if( p_module->psz_longname )
584 fprintf( file, "###\n### %s\n###\n", p_module->psz_longname );
586 for( i = 0; i < p_module->i_config_lines; i++ )
588 if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
592 switch( p_module->p_config[i].i_type )
594 case MODULE_CONFIG_ITEM_BOOL:
595 case MODULE_CONFIG_ITEM_INTEGER:
596 if( p_module->p_config[i].psz_text )
597 fprintf( file, "# %s\n", p_module->p_config[i].psz_text );
598 fprintf( file, "%s=%i\n", p_module->p_config[i].psz_name,
599 p_module->p_config[i].i_value );
603 if( p_module->p_config[i].psz_value )
605 if( p_module->p_config[i].psz_text )
606 fprintf( file, "# %s\n",
607 p_module->p_config[i].psz_text );
608 fprintf( file, "%s=%s\n", p_module->p_config[i].psz_name,
609 p_module->p_config[i].psz_value );
614 fprintf( file, "\n" );
619 * Restore old settings from the config in file
621 fputs( p_bigbuffer, file );
625 free( psz_filename );
626 vlc_mutex_unlock( &p_main->config_lock );
631 /* Following functions are local. */
633 /*****************************************************************************
634 * GetHomeDir: find the user's home directory.
635 *****************************************************************************
636 * This function will try by different ways to find the user's home path.
637 *****************************************************************************/
638 static char *GetHomeDir( void )
640 char *p_tmp, *p_homedir = NULL;
642 #if defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWUID)
643 struct passwd *p_pw = NULL;
646 #if defined(HAVE_GETPWUID_R)
649 char *p_buffer = NULL;
652 p_buffer = (char *)malloc( bufsize );
654 if( ( ret = getpwuid_r( getuid(), &pwd, p_buffer, bufsize, &p_pw ) ) < 0 )
655 #elif defined(HAVE_GETPWUID)
656 if( ( p_pw = getpwuid( getuid() ) ) == NULL )
659 if( ( p_tmp = getenv( "HOME" ) ) == NULL )
661 intf_ErrMsg( "config error: unable to get home directory, "
662 "using /tmp instead" );
663 p_homedir = strdup( "/tmp" );
665 else p_homedir = strdup( p_tmp );
667 #if defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWUID)
670 if( p_pw ) p_homedir = strdup( p_pw->pw_dir );
674 #if defined(HAVE_GETPWUID_R)
675 if( p_buffer ) free( p_buffer );