1 /*****************************************************************************
2 * configuration.c management of the modules configuration
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: configuration.c,v 1.45 2002/11/11 14:39:12 sam 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 *****************************************************************************/
26 #include <stdio.h> /* sprintf() */
27 #include <stdlib.h> /* free(), strtol() */
28 #include <string.h> /* strdup() */
30 # include <errno.h> /* errno */
34 # include <unistd.h> /* getuid() */
37 #ifdef HAVE_GETOPT_LONG
39 # include <getopt.h> /* getopt() */
42 # include "../extras/getopt.h"
45 #if defined(HAVE_GETPWUID)
46 #include <pwd.h> /* getpwuid() */
49 #if defined( HAVE_SYS_STAT_H )
50 # include <sys/stat.h>
52 #if defined( HAVE_SYS_TYPES_H )
53 # include <sys/types.h>
56 /*****************************************************************************
57 * config_GetInt: get the value of an int variable
58 *****************************************************************************
59 * This function is used to get the value of variables which are internally
60 * represented by an integer (CONFIG_ITEM_INTEGER and
62 *****************************************************************************/
63 int __config_GetInt( vlc_object_t *p_this, const char *psz_name )
65 module_config_t *p_config;
67 p_config = config_FindConfig( p_this, psz_name );
72 msg_Err( p_this, "option %s does not exist", psz_name );
75 if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
76 (p_config->i_type!=CONFIG_ITEM_BOOL) )
78 msg_Err( p_this, "option %s does not refer to an int", psz_name );
82 return p_config->i_value;
85 /*****************************************************************************
86 * config_GetFloat: get the value of a float variable
87 *****************************************************************************
88 * This function is used to get the value of variables which are internally
89 * represented by a float (CONFIG_ITEM_FLOAT).
90 *****************************************************************************/
91 float __config_GetFloat( vlc_object_t *p_this, const char *psz_name )
93 module_config_t *p_config;
95 p_config = config_FindConfig( p_this, psz_name );
100 msg_Err( p_this, "option %s does not exist", psz_name );
103 if( p_config->i_type != CONFIG_ITEM_FLOAT )
105 msg_Err( p_this, "option %s does not refer to a float", psz_name );
109 return p_config->f_value;
112 /*****************************************************************************
113 * config_GetPsz: get the string value of a string variable
114 *****************************************************************************
115 * This function is used to get the value of variables which are internally
116 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
117 * and CONFIG_ITEM_MODULE).
119 * Important note: remember to free() the returned char* because it's a
120 * duplicate of the actual value. It isn't safe to return a pointer to the
121 * actual value as it can be modified at any time.
122 *****************************************************************************/
123 char * __config_GetPsz( vlc_object_t *p_this, const char *psz_name )
125 module_config_t *p_config;
126 char *psz_value = NULL;
128 p_config = config_FindConfig( p_this, psz_name );
133 msg_Err( p_this, "option %s does not exist", psz_name );
136 if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
137 (p_config->i_type!=CONFIG_ITEM_FILE) &&
138 (p_config->i_type!=CONFIG_ITEM_MODULE) )
140 msg_Err( p_this, "option %s does not refer to a string", psz_name );
144 /* return a copy of the string */
145 vlc_mutex_lock( p_config->p_lock );
146 if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
147 vlc_mutex_unlock( p_config->p_lock );
152 /*****************************************************************************
153 * config_PutPsz: set the string value of a string variable
154 *****************************************************************************
155 * This function is used to set the value of variables which are internally
156 * represented by a string (CONFIG_ITEM_STRING, CONFIG_ITEM_FILE,
157 * and CONFIG_ITEM_MODULE).
158 *****************************************************************************/
159 void __config_PutPsz( vlc_object_t *p_this,
160 const char *psz_name, const char *psz_value )
162 module_config_t *p_config;
164 p_config = config_FindConfig( p_this, psz_name );
169 msg_Err( p_this, "option %s does not exist", psz_name );
172 if( (p_config->i_type!=CONFIG_ITEM_STRING) &&
173 (p_config->i_type!=CONFIG_ITEM_FILE) &&
174 (p_config->i_type!=CONFIG_ITEM_MODULE) )
176 msg_Err( p_this, "option %s does not refer to a string", psz_name );
180 vlc_mutex_lock( p_config->p_lock );
182 /* free old string */
183 if( p_config->psz_value ) free( p_config->psz_value );
185 if( psz_value ) p_config->psz_value = strdup( psz_value );
186 else p_config->psz_value = NULL;
188 vlc_mutex_unlock( p_config->p_lock );
190 if( p_config->pf_callback )
192 p_config->pf_callback( p_this );
196 /*****************************************************************************
197 * config_PutInt: set the integer value of an int variable
198 *****************************************************************************
199 * This function is used to set the value of variables which are internally
200 * represented by an integer (CONFIG_ITEM_INTEGER and
202 *****************************************************************************/
203 void __config_PutInt( vlc_object_t *p_this, const char *psz_name, int i_value )
205 module_config_t *p_config;
207 p_config = config_FindConfig( p_this, psz_name );
212 msg_Err( p_this, "option %s does not exist", psz_name );
215 if( (p_config->i_type!=CONFIG_ITEM_INTEGER) &&
216 (p_config->i_type!=CONFIG_ITEM_BOOL) )
218 msg_Err( p_this, "option %s does not refer to an int", psz_name );
222 p_config->i_value = i_value;
224 if( p_config->pf_callback )
226 p_config->pf_callback( p_this );
230 /*****************************************************************************
231 * config_PutFloat: set the value of a float variable
232 *****************************************************************************
233 * This function is used to set the value of variables which are internally
234 * represented by a float (CONFIG_ITEM_FLOAT).
235 *****************************************************************************/
236 void __config_PutFloat( vlc_object_t *p_this,
237 const char *psz_name, float f_value )
239 module_config_t *p_config;
241 p_config = config_FindConfig( p_this, psz_name );
246 msg_Err( p_this, "option %s does not exist", psz_name );
249 if( p_config->i_type != CONFIG_ITEM_FLOAT )
251 msg_Err( p_this, "option %s does not refer to a float", psz_name );
255 p_config->f_value = f_value;
257 if( p_config->pf_callback )
259 p_config->pf_callback( p_this );
263 /*****************************************************************************
264 * config_FindConfig: find the config structure associated with an option.
265 *****************************************************************************
266 * FIXME: This function really needs to be optimized.
267 * FIXME: And now even more.
268 *****************************************************************************/
269 module_config_t *config_FindConfig( vlc_object_t *p_this, const char *psz_name )
272 module_t **pp_parser;
273 module_config_t *p_item;
275 if( !psz_name ) return NULL;
277 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
279 for( pp_parser = (module_t **)p_list->pp_objects ;
283 if( !(*pp_parser)->i_config_items )
286 for( p_item = (*pp_parser)->p_config;
287 p_item->i_type != CONFIG_HINT_END;
290 if( p_item->i_type & CONFIG_HINT )
293 if( !strcmp( psz_name, p_item->psz_name ) )
295 vlc_list_release( p_list );
301 vlc_list_release( p_list );
306 /*****************************************************************************
307 * config_Duplicate: creates a duplicate of a module's configuration data.
308 *****************************************************************************
309 * Unfortunatly we cannot work directly with the module's config data as
310 * this module might be unloaded from memory at any time (remember HideModule).
311 * This is why we need to create an exact copy of the config data.
312 *****************************************************************************/
313 void config_Duplicate( module_t *p_module, module_config_t *p_orig )
315 int i, j, i_lines = 1;
316 module_config_t *p_item;
318 /* Calculate the structure length */
319 p_module->i_config_items = 0;
320 p_module->i_bool_items = 0;
322 for( p_item = p_orig; p_item->i_type != CONFIG_HINT_END; p_item++ )
326 if( p_item->i_type & CONFIG_ITEM )
328 p_module->i_config_items++;
331 if( p_item->i_type == CONFIG_ITEM_BOOL )
333 p_module->i_bool_items++;
337 /* Allocate memory */
338 p_module->p_config = (module_config_t *)malloc( sizeof(module_config_t)
340 if( p_module->p_config == NULL )
342 msg_Err( p_module, "config error: can't duplicate p_config" );
346 /* Do the duplication job */
347 for( i = 0; i < i_lines ; i++ )
349 p_module->p_config[i].i_type = p_orig[i].i_type;
350 p_module->p_config[i].i_short = p_orig[i].i_short;
351 p_module->p_config[i].i_value = p_orig[i].i_value;
352 p_module->p_config[i].f_value = p_orig[i].f_value;
353 p_module->p_config[i].b_dirty = p_orig[i].b_dirty;
355 p_module->p_config[i].psz_type = p_orig[i].psz_type ?
356 strdup( _(p_orig[i].psz_type) ) : NULL;
357 p_module->p_config[i].psz_name = p_orig[i].psz_name ?
358 strdup( _(p_orig[i].psz_name) ) : NULL;
359 p_module->p_config[i].psz_text = p_orig[i].psz_text ?
360 strdup( _(p_orig[i].psz_text) ) : NULL;
361 p_module->p_config[i].psz_longtext = p_orig[i].psz_longtext ?
362 strdup( _(p_orig[i].psz_longtext) ) : NULL;
363 p_module->p_config[i].psz_value = p_orig[i].psz_value ?
364 strdup( p_orig[i].psz_value ) : NULL;
366 p_module->p_config[i].p_lock = &p_module->object_lock;
368 /* duplicate the string list */
369 p_module->p_config[i].ppsz_list = NULL;
370 if( p_orig[i].ppsz_list )
372 for( j = 0; p_orig[i].ppsz_list[j]; j++ );
373 p_module->p_config[i].ppsz_list = malloc( (j+1) *sizeof(char *) );
374 if( p_module->p_config[i].ppsz_list )
376 for( j = 0; p_orig[i].ppsz_list[j]; j++ )
377 p_module->p_config[i].ppsz_list[j] =
378 strdup( p_orig[i].ppsz_list[j] );
380 p_module->p_config[i].ppsz_list[j] = NULL;
383 p_module->p_config[i].pf_callback = p_orig[i].pf_callback;
387 /*****************************************************************************
388 * config_Free: frees a duplicated module's configuration data.
389 *****************************************************************************
390 * This function frees all the data duplicated by config_Duplicate.
391 *****************************************************************************/
392 void config_Free( module_t *p_module )
394 module_config_t *p_item = p_module->p_config;
402 for( ; p_item->i_type != CONFIG_HINT_END ; p_item++ )
404 if( p_item->psz_type )
405 free( p_item->psz_type );
407 if( p_item->psz_name )
408 free( p_item->psz_name );
410 if( p_item->psz_text )
411 free( p_item->psz_text );
413 if( p_item->psz_longtext )
414 free( p_item->psz_longtext );
416 if( p_item->psz_value )
417 free( p_item->psz_value );
419 if( p_item->ppsz_list )
421 for( i = 0; p_item->ppsz_list[i]; i++ )
422 free(p_item->ppsz_list[i]);
423 free( p_item->ppsz_list );
427 free( p_module->p_config );
428 p_module->p_config = NULL;
431 /*****************************************************************************
432 * config_SetCallbacks: sets callback functions in the duplicate p_config.
433 *****************************************************************************
434 * Unfortunatly we cannot work directly with the module's config data as
435 * this module might be unloaded from memory at any time (remember HideModule).
436 * This is why we need to duplicate callbacks each time we reload the module.
437 *****************************************************************************/
438 void config_SetCallbacks( module_config_t *p_new, module_config_t *p_orig )
440 while( p_new->i_type != CONFIG_HINT_END )
442 p_new->pf_callback = p_orig->pf_callback;
448 /*****************************************************************************
449 * config_UnsetCallbacks: unsets callback functions in the duplicate p_config.
450 *****************************************************************************
451 * We simply undo what we did in config_SetCallbacks.
452 *****************************************************************************/
453 void config_UnsetCallbacks( module_config_t *p_new )
455 while( p_new->i_type != CONFIG_HINT_END )
457 p_new->pf_callback = NULL;
462 /*****************************************************************************
463 * config_LoadConfigFile: loads the configuration file.
464 *****************************************************************************
465 * This function is called to load the config options stored in the config
467 *****************************************************************************/
468 int __config_LoadConfigFile( vlc_object_t *p_this, const char *psz_module_name )
471 module_t **pp_parser;
472 module_config_t *p_item;
475 char *p_index, *psz_option_name, *psz_option_value;
476 char *psz_filename, *psz_homedir;
478 psz_homedir = p_this->p_vlc->psz_homedir;
481 msg_Err( p_this, "psz_homedir is null" );
484 psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
485 strlen(psz_homedir) + 1 );
488 msg_Err( p_this, "out of memory" );
491 sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
493 msg_Dbg( p_this, "opening config file %s", psz_filename );
495 /* Acquire config file lock */
496 vlc_mutex_lock( &p_this->p_vlc->config_lock );
498 file = fopen( psz_filename, "rt" );
501 msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
502 free( psz_filename );
503 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
507 /* Look for the selected module, if NULL then save everything */
508 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
510 for( pp_parser = (module_t **)p_list->pp_objects ;
516 && strcmp( psz_module_name, (*pp_parser)->psz_object_name ) )
521 /* The config file is organized in sections, one per module. Look for
522 * the interesting section ( a section is of the form [foo] ) */
523 fseek( file, 0L, SEEK_SET );
524 while( fgets( line, 1024, file ) )
527 && (p_index = strchr(line,']'))
528 && (p_index - &line[1] == strlen((*pp_parser)->psz_object_name))
529 && !memcmp( &line[1], (*pp_parser)->psz_object_name,
530 strlen((*pp_parser)->psz_object_name) ) )
533 msg_Dbg( p_this, "loading config for module \"%s\"",
534 (*pp_parser)->psz_object_name );
540 /* either we found the section or we're at the EOF */
542 /* Now try to load the options in this section */
543 while( fgets( line, 1024, file ) )
545 if( line[0] == '[' ) break; /* end of section */
547 /* ignore comments or empty lines */
548 if( (line[0] == '#') || (line[0] == '\n') || (line[0] == (char)0) )
551 /* get rid of line feed */
552 if( line[strlen(line)-1] == '\n' )
553 line[strlen(line)-1] = (char)0;
555 /* look for option name */
556 psz_option_name = line;
557 psz_option_value = NULL;
558 p_index = strchr( line, '=' );
559 if( !p_index ) break; /* this ain't an option!!! */
562 psz_option_value = p_index + 1;
564 if( !(*pp_parser)->i_config_items )
569 /* try to match this option with one of the module's options */
570 for( p_item = (*pp_parser)->p_config;
571 p_item->i_type != CONFIG_HINT_END;
574 if( p_item->i_type & CONFIG_HINT )
578 if( !strcmp( p_item->psz_name, psz_option_name ) )
581 switch( p_item->i_type )
583 case CONFIG_ITEM_BOOL:
584 case CONFIG_ITEM_INTEGER:
585 if( !*psz_option_value )
586 break; /* ignore empty option */
587 p_item->i_value = atoi( psz_option_value);
589 msg_Dbg( p_this, "option \"%s\", value %i",
590 p_item->psz_name, p_item->i_value );
594 case CONFIG_ITEM_FLOAT:
595 if( !*psz_option_value )
596 break; /* ignore empty option */
597 p_item->f_value = (float)atof( psz_option_value);
599 msg_Dbg( p_this, "option \"%s\", value %f",
600 p_item->psz_name, (double)p_item->f_value );
605 vlc_mutex_lock( p_item->p_lock );
607 /* free old string */
608 if( p_item->psz_value )
609 free( p_item->psz_value );
611 p_item->psz_value = *psz_option_value ?
612 strdup( psz_option_value ) : NULL;
614 vlc_mutex_unlock( p_item->p_lock );
617 msg_Dbg( p_this, "option \"%s\", value \"%s\"",
619 p_item->psz_value ? p_item->psz_value : "" );
629 vlc_list_release( p_list );
632 free( psz_filename );
634 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
639 /*****************************************************************************
640 * config_SaveConfigFile: Save a module's config options.
641 *****************************************************************************
642 * This will save the specified module's config options to the config file.
643 * If psz_module_name is NULL then we save all the modules config options.
644 * It's no use to save the config options that kept their default values, so
645 * we'll try to be a bit clever here.
647 * When we save we mustn't delete the config options of the modules that
648 * haven't been loaded. So we cannot just create a new config file with the
649 * config structures we've got in memory.
650 * I don't really know how to deal with this nicely, so I will use a completly
652 * I will load the config file in memory, but skipping all the sections of the
653 * modules we want to save. Then I will create a brand new file, dump the file
654 * loaded in memory and then append the sections of the modules we want to
657 *****************************************************************************/
658 int __config_SaveConfigFile( vlc_object_t *p_this, const char *psz_module_name )
660 module_t **pp_parser;
662 module_config_t *p_item;
664 char p_line[1024], *p_index2;
666 char *p_bigbuffer, *p_index;
668 char *psz_filename, *psz_homedir;
670 /* Acquire config file lock */
671 vlc_mutex_lock( &p_this->p_vlc->config_lock );
673 psz_homedir = p_this->p_vlc->psz_homedir;
676 msg_Err( p_this, "psz_homedir is null" );
677 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
680 psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
681 strlen(psz_homedir) + 1 );
684 msg_Err( p_this, "out of memory" );
685 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
688 sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
690 #if defined( UNDER_CE )
692 wchar_t psz_new[ MAX_PATH ];
693 MultiByteToWideChar( CP_ACP, 0, psz_filename, -1, psz_new, MAX_PATH );
694 if( CreateDirectory( psz_new, NULL ) )
696 msg_Err( p_this, "could not create %s", psz_filename );
700 #elif defined( HAVE_ERRNO_H )
701 # if defined( WIN32 )
702 if( mkdir( psz_filename ) && errno != EEXIST )
704 if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
707 msg_Err( p_this, "could not create %s (%s)",
708 psz_filename, strerror(errno) );
712 if( mkdir( psz_filename ) )
714 msg_Err( p_this, "could not create %s", psz_filename );
719 strcat( psz_filename, "/" CONFIG_FILE );
722 msg_Dbg( p_this, "opening config file %s", psz_filename );
724 file = fopen( psz_filename, "rt" );
727 msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
731 /* look for file size */
732 fseek( file, 0L, SEEK_END );
733 i_sizebuf = ftell( file );
734 fseek( file, 0L, SEEK_SET );
737 p_bigbuffer = p_index = malloc( i_sizebuf+1 );
740 msg_Err( p_this, "out of memory" );
741 if( file ) fclose( file );
742 free( psz_filename );
743 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
748 /* List all available modules */
749 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
751 /* backup file into memory, we only need to backup the sections we won't
754 while( file && fgets( p_line, 1024, file ) )
756 if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
759 /* we found a section, check if we need to do a backup */
760 for( pp_parser = (module_t **)p_list->pp_objects ;
764 if( ((p_index2 - &p_line[1])
765 == strlen((*pp_parser)->psz_object_name) ) &&
766 !memcmp( &p_line[1], (*pp_parser)->psz_object_name,
767 strlen((*pp_parser)->psz_object_name) ) )
769 if( !psz_module_name )
771 else if( !strcmp( psz_module_name,
772 (*pp_parser)->psz_object_name ) )
779 /* we don't have this section in our list so we need to back
782 msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
794 /* save line if requested and line is valid (doesn't begin with a
795 * space, tab, or eol) */
796 if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
797 && (p_line[0] != '\t') )
799 strcpy( p_index, p_line );
800 p_index += strlen( p_line );
803 if( file ) fclose( file );
807 * Save module config in file
810 file = fopen( psz_filename, "wt" );
813 msg_Warn( p_this, "could not open config file %s for writing",
815 free( psz_filename );
816 vlc_list_release( p_list );
817 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
821 fprintf( file, "###\n### " COPYRIGHT_MESSAGE "\n###\n\n" );
823 /* Look for the selected module, if NULL then save everything */
824 for( pp_parser = (module_t **)p_list->pp_objects ;
829 if( psz_module_name && strcmp( psz_module_name,
830 (*pp_parser)->psz_object_name ) )
833 if( !(*pp_parser)->i_config_items )
836 msg_Dbg( p_this, "saving config for module \"%s\"",
837 (*pp_parser)->psz_object_name );
839 fprintf( file, "[%s]", (*pp_parser)->psz_object_name );
840 if( (*pp_parser)->psz_longname )
841 fprintf( file, " # %s\n\n", (*pp_parser)->psz_longname );
843 fprintf( file, "\n\n" );
845 for( p_item = (*pp_parser)->p_config;
846 p_item->i_type != CONFIG_HINT_END;
849 if( p_item->i_type & CONFIG_HINT )
853 switch( p_item->i_type )
855 case CONFIG_ITEM_BOOL:
856 case CONFIG_ITEM_INTEGER:
857 if( p_item->psz_text )
858 fprintf( file, "# %s (%s)\n", p_item->psz_text,
859 (p_item->i_type == CONFIG_ITEM_BOOL) ?
860 _("boolean") : _("integer") );
861 fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
864 case CONFIG_ITEM_FLOAT:
865 if( p_item->psz_text )
866 fprintf( file, "# %s (%s)\n", p_item->psz_text,
868 fprintf( file, "%s=%f\n", p_item->psz_name,
869 (double)p_item->f_value );
873 if( p_item->psz_text )
874 fprintf( file, "# %s (%s)\n", p_item->psz_text,
876 fprintf( file, "%s=%s\n", p_item->psz_name,
877 p_item->psz_value ? p_item->psz_value : "" );
881 fprintf( file, "\n" );
884 vlc_list_release( p_list );
887 * Restore old settings from the config in file
889 fputs( p_bigbuffer, file );
893 free( psz_filename );
894 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
899 /*****************************************************************************
900 * config_LoadCmdLine: parse command line
901 *****************************************************************************
902 * Parse command line for configuration options.
903 * Now that the module_bank has been initialized, we can dynamically
904 * generate the longopts structure used by getops. We have to do it this way
905 * because we don't know (and don't want to know) in advance the configuration
906 * options used (ie. exported) by each module.
907 *****************************************************************************/
908 int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
909 vlc_bool_t b_ignore_errors )
911 int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
912 module_t **pp_parser;
914 module_config_t *p_item;
915 struct option *p_longopts;
918 module_config_t *pp_shortopts[256];
921 /* Set default configuration and copy arguments */
922 p_this->p_vlc->i_argc = *pi_argc;
923 p_this->p_vlc->ppsz_argv = ppsz_argv;
925 p_this->p_vlc->p_channel = NULL;
928 /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
929 * is the PSN - process serial number (a unique PID-ish thingie)
930 * still ok for real Darwin & when run from command line */
931 if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
932 /* for example -psn_0_9306113 */
934 /* GDMF!... I can't do this or else the MacOSX window server will
935 * not pick up the PSN and not register the app and we crash...
936 * hence the following kludge otherwise we'll get confused w/ argv[1]
937 * being an input file name */
939 ppsz_argv[ 1 ] = NULL;
941 *pi_argc = *pi_argc - 1;
947 /* List all modules */
948 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
951 * Generate the longopts and shortopts structures used by getopt_long
955 for( pp_parser = (module_t **)p_list->pp_objects ;
959 /* count the number of exported configuration options (to allocate
960 * longopts). We also need to allocate space for too options when
961 * dealing with boolean to allow for --foo and --no-foo */
962 i_opts += (*pp_parser)->i_config_items
963 + 2 * (*pp_parser)->i_bool_items;
966 p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
967 if( p_longopts == NULL )
969 msg_Err( p_this, "out of memory" );
970 vlc_list_release( p_list );
974 psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
975 if( psz_shortopts == NULL )
977 msg_Err( p_this, "out of memory" );
979 vlc_list_release( p_list );
983 /* If we are requested to ignore errors, then we must work on a copy
984 * of the ppsz_argv array, otherwise getopt_long will reorder it for
985 * us, ignoring the arity of the options */
986 if( b_ignore_errors )
988 ppsz_argv = (char**)malloc( *pi_argc * sizeof(char *) );
989 if( ppsz_argv == NULL )
991 msg_Err( p_this, "out of memory" );
992 free( psz_shortopts );
994 vlc_list_release( p_list );
997 memcpy( ppsz_argv, p_this->p_vlc->ppsz_argv,
998 *pi_argc * sizeof(char *) );
1002 for( i_index = 0; i_index < 256; i_index++ )
1004 pp_shortopts[i_index] = NULL;
1007 /* Fill the p_longopts and psz_shortopts structures */
1009 for( pp_parser = (module_t **)p_list->pp_objects ;
1013 if( !(*pp_parser)->i_config_items )
1016 for( p_item = (*pp_parser)->p_config;
1017 p_item->i_type != CONFIG_HINT_END;
1021 if( p_item->i_type & CONFIG_HINT )
1024 /* Add item to long options */
1025 p_longopts[i_index].name = strdup( p_item->psz_name );
1026 if( p_longopts[i_index].name == NULL ) continue;
1027 p_longopts[i_index].has_arg =
1028 (p_item->i_type == CONFIG_ITEM_BOOL)?
1029 no_argument : required_argument;
1030 p_longopts[i_index].flag = &flag;
1031 p_longopts[i_index].val = 0;
1034 /* When dealing with bools we also need to add the --no-foo
1036 if( p_item->i_type == CONFIG_ITEM_BOOL )
1038 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
1039 if( psz_name == NULL ) continue;
1040 strcpy( psz_name, "no" );
1041 strcat( psz_name, p_item->psz_name );
1043 p_longopts[i_index].name = psz_name;
1044 p_longopts[i_index].has_arg = no_argument;
1045 p_longopts[i_index].flag = &flag;
1046 p_longopts[i_index].val = 1;
1049 psz_name = malloc( strlen(p_item->psz_name) + 4 );
1050 if( psz_name == NULL ) continue;
1051 strcpy( psz_name, "no-" );
1052 strcat( psz_name, p_item->psz_name );
1054 p_longopts[i_index].name = psz_name;
1055 p_longopts[i_index].has_arg = no_argument;
1056 p_longopts[i_index].flag = &flag;
1057 p_longopts[i_index].val = 1;
1061 /* If item also has a short option, add it */
1062 if( p_item->i_short )
1064 pp_shortopts[(int)p_item->i_short] = p_item;
1065 psz_shortopts[i_shortopts] = p_item->i_short;
1067 if( p_item->i_type != CONFIG_ITEM_BOOL )
1069 psz_shortopts[i_shortopts] = ':';
1072 if( p_item->i_short == 'v' )
1074 psz_shortopts[i_shortopts] = ':';
1082 /* We don't need the module list anymore */
1083 vlc_list_release( p_list );
1085 /* Close the longopts and shortopts structures */
1086 memset( &p_longopts[i_index], 0, sizeof(struct option) );
1087 psz_shortopts[i_shortopts] = '\0';
1090 * Parse the command line options
1094 while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
1095 p_longopts, &i_index ) ) != EOF )
1097 /* A long option has been recognized */
1100 module_config_t *p_conf;
1101 char *psz_name = (char *)p_longopts[i_index].name;
1103 /* Check if we deal with a --nofoo or --no-foo long option */
1104 if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
1106 /* Store the configuration option */
1107 p_conf = config_FindConfig( p_this, psz_name );
1109 if( p_conf ) switch( p_conf->i_type )
1111 case CONFIG_ITEM_STRING:
1112 case CONFIG_ITEM_FILE:
1113 case CONFIG_ITEM_MODULE:
1114 config_PutPsz( p_this, psz_name, optarg );
1116 case CONFIG_ITEM_INTEGER:
1117 config_PutInt( p_this, psz_name, atoi(optarg));
1119 case CONFIG_ITEM_FLOAT:
1120 config_PutFloat( p_this, psz_name, (float)atof(optarg) );
1122 case CONFIG_ITEM_BOOL:
1123 config_PutInt( p_this, psz_name, !flag );
1130 /* A short option has been recognized */
1131 if( pp_shortopts[i_cmd] != NULL )
1133 switch( pp_shortopts[i_cmd]->i_type )
1135 case CONFIG_ITEM_STRING:
1136 case CONFIG_ITEM_FILE:
1137 case CONFIG_ITEM_MODULE:
1138 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
1140 case CONFIG_ITEM_INTEGER:
1145 if( *optarg == 'v' ) /* eg. -vvv */
1148 while( *optarg == 'v' )
1156 i_verbose += atoi( optarg ); /* eg. -v2 */
1161 i_verbose++; /* -v */
1163 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1168 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1172 case CONFIG_ITEM_BOOL:
1173 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
1180 /* Internal error: unknown option */
1181 if( !b_ignore_errors )
1183 fprintf( stderr, "unknown option `%s'\n", ppsz_argv[optind-1] );
1184 fprintf( stderr, "Try `%s --help' for more information.\n",
1185 p_this->p_vlc->psz_object_name );
1188 free( psz_shortopts );
1189 if( b_ignore_errors ) free( ppsz_argv );
1194 /* Free allocated resources */
1195 for( i_index = 0; p_longopts[i_index].name; i_index++ )
1196 free( (char *)p_longopts[i_index].name );
1198 free( psz_shortopts );
1199 if( b_ignore_errors ) free( ppsz_argv );
1204 /*****************************************************************************
1205 * config_GetHomeDir: find the user's home directory.
1206 *****************************************************************************
1207 * This function will try by different ways to find the user's home path.
1208 * Note that this function is not reentrant, it should be called only once
1209 * at the beginning of main where the result will be stored for later use.
1210 *****************************************************************************/
1211 char *config_GetHomeDir( void )
1213 char *p_tmp, *p_homedir = NULL;
1215 #if defined(HAVE_GETPWUID)
1216 struct passwd *p_pw = NULL;
1219 #if defined(WIN32) || defined(UNDER_CE)
1220 typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
1222 # define CSIDL_FLAG_CREATE 0x8000
1223 # define CSIDL_APPDATA 0x1A
1224 # define SHGFP_TYPE_CURRENT 0
1226 HINSTANCE shfolder_dll;
1227 SHGETFOLDERPATH SHGetFolderPath ;
1229 /* load the shell32 dll to retreive SHGetFolderPath */
1230 if( ( shfolder_dll = LoadLibrary("shfolder.dll") ) != NULL )
1232 SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
1233 "SHGetFolderPathA" );
1234 if ( SHGetFolderPath != NULL )
1236 p_homedir = (char *)malloc( MAX_PATH );
1242 /* get the "Application Data" folder for the current user */
1243 if( S_OK == SHGetFolderPath( NULL,
1244 CSIDL_APPDATA | CSIDL_FLAG_CREATE,
1245 NULL, SHGFP_TYPE_CURRENT,
1248 FreeLibrary( shfolder_dll );
1253 FreeLibrary( shfolder_dll );
1257 #if defined(HAVE_GETPWUID)
1258 if( ( p_pw = getpwuid( getuid() ) ) == NULL )
1261 if( ( p_tmp = getenv( "HOME" ) ) == NULL )
1263 if( ( p_tmp = getenv( "TMP" ) ) == NULL )
1269 p_homedir = strdup( p_tmp );
1271 #if defined(HAVE_GETPWUID)
1274 p_homedir = strdup( p_pw->pw_dir );