1 /*****************************************************************************
2 * configuration.c management of the modules configuration
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: configuration.c,v 1.43 2002/11/10 18:04:23 sam Exp $
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] ) */
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 );
691 # if defined( WIN32 )
692 if( mkdir( psz_filename ) && errno != EEXIST )
694 if( mkdir( psz_filename, 0755 ) && errno != EEXIST )
697 msg_Err( p_this, "could not create %s (%s)",
698 psz_filename, strerror(errno) );
702 if( mkdir( psz_filename ) )
704 msg_Err( p_this, "could not create %s", psz_filename );
709 strcat( psz_filename, "/" CONFIG_FILE );
712 msg_Dbg( p_this, "opening config file %s", psz_filename );
714 file = fopen( psz_filename, "rt" );
717 msg_Warn( p_this, "config file %s does not exist yet", psz_filename );
721 /* look for file size */
722 fseek( file, 0, SEEK_END );
723 i_sizebuf = ftell( file );
727 p_bigbuffer = p_index = malloc( i_sizebuf+1 );
730 msg_Err( p_this, "out of memory" );
731 if( file ) fclose( file );
732 free( psz_filename );
733 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
738 /* List all available modules */
739 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
741 /* backup file into memory, we only need to backup the sections we won't
744 while( file && fgets( p_line, 1024, file ) )
746 if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
749 /* we found a section, check if we need to do a backup */
750 for( pp_parser = (module_t **)p_list->pp_objects ;
754 if( ((p_index2 - &p_line[1])
755 == strlen((*pp_parser)->psz_object_name) ) &&
756 !memcmp( &p_line[1], (*pp_parser)->psz_object_name,
757 strlen((*pp_parser)->psz_object_name) ) )
759 if( !psz_module_name )
761 else if( !strcmp( psz_module_name,
762 (*pp_parser)->psz_object_name ) )
769 /* we don't have this section in our list so we need to back
772 msg_Dbg( p_this, "backing up config for unknown module \"%s\"",
784 /* save line if requested and line is valid (doesn't begin with a
785 * space, tab, or eol) */
786 if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
787 && (p_line[0] != '\t') )
789 strcpy( p_index, p_line );
790 p_index += strlen( p_line );
793 if( file ) fclose( file );
797 * Save module config in file
800 file = fopen( psz_filename, "wt" );
803 msg_Warn( p_this, "could not open config file %s for writing",
805 free( psz_filename );
806 vlc_list_release( p_list );
807 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
811 fprintf( file, "###\n### " COPYRIGHT_MESSAGE "\n###\n\n" );
813 /* Look for the selected module, if NULL then save everything */
814 for( pp_parser = (module_t **)p_list->pp_objects ;
819 if( psz_module_name && strcmp( psz_module_name,
820 (*pp_parser)->psz_object_name ) )
823 if( !(*pp_parser)->i_config_items )
826 msg_Dbg( p_this, "saving config for module \"%s\"",
827 (*pp_parser)->psz_object_name );
829 fprintf( file, "[%s]", (*pp_parser)->psz_object_name );
830 if( (*pp_parser)->psz_longname )
831 fprintf( file, " # %s\n\n", (*pp_parser)->psz_longname );
833 fprintf( file, "\n\n" );
835 for( p_item = (*pp_parser)->p_config;
836 p_item->i_type != CONFIG_HINT_END;
839 if( p_item->i_type & CONFIG_HINT )
843 switch( p_item->i_type )
845 case CONFIG_ITEM_BOOL:
846 case CONFIG_ITEM_INTEGER:
847 if( p_item->psz_text )
848 fprintf( file, "# %s (%s)\n", p_item->psz_text,
849 (p_item->i_type == CONFIG_ITEM_BOOL) ?
850 _("boolean") : _("integer") );
851 fprintf( file, "%s=%i\n", p_item->psz_name, p_item->i_value );
854 case CONFIG_ITEM_FLOAT:
855 if( p_item->psz_text )
856 fprintf( file, "# %s (%s)\n", p_item->psz_text,
858 fprintf( file, "%s=%f\n", p_item->psz_name,
859 (double)p_item->f_value );
863 if( p_item->psz_text )
864 fprintf( file, "# %s (%s)\n", p_item->psz_text,
866 fprintf( file, "%s=%s\n", p_item->psz_name,
867 p_item->psz_value ? p_item->psz_value : "" );
871 fprintf( file, "\n" );
874 vlc_list_release( p_list );
877 * Restore old settings from the config in file
879 fputs( p_bigbuffer, file );
883 free( psz_filename );
884 vlc_mutex_unlock( &p_this->p_vlc->config_lock );
889 /*****************************************************************************
890 * config_LoadCmdLine: parse command line
891 *****************************************************************************
892 * Parse command line for configuration options.
893 * Now that the module_bank has been initialized, we can dynamically
894 * generate the longopts structure used by getops. We have to do it this way
895 * because we don't know (and don't want to know) in advance the configuration
896 * options used (ie. exported) by each module.
897 *****************************************************************************/
898 int __config_LoadCmdLine( vlc_object_t *p_this, int *pi_argc, char *ppsz_argv[],
899 vlc_bool_t b_ignore_errors )
901 int i_cmd, i_index, i_opts, i_shortopts, flag, i_verbose = 0;
902 module_t **pp_parser;
904 module_config_t *p_item;
905 struct option *p_longopts;
908 module_config_t *pp_shortopts[256];
911 /* Set default configuration and copy arguments */
912 p_this->p_vlc->i_argc = *pi_argc;
913 p_this->p_vlc->ppsz_argv = ppsz_argv;
915 p_this->p_vlc->p_channel = NULL;
918 /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
919 * is the PSN - process serial number (a unique PID-ish thingie)
920 * still ok for real Darwin & when run from command line */
921 if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
922 /* for example -psn_0_9306113 */
924 /* GDMF!... I can't do this or else the MacOSX window server will
925 * not pick up the PSN and not register the app and we crash...
926 * hence the following kludge otherwise we'll get confused w/ argv[1]
927 * being an input file name */
929 ppsz_argv[ 1 ] = NULL;
931 *pi_argc = *pi_argc - 1;
937 /* List all modules */
938 p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
941 * Generate the longopts and shortopts structures used by getopt_long
945 for( pp_parser = (module_t **)p_list->pp_objects ;
949 /* count the number of exported configuration options (to allocate
950 * longopts). We also need to allocate space for too options when
951 * dealing with boolean to allow for --foo and --no-foo */
952 i_opts += (*pp_parser)->i_config_items
953 + 2 * (*pp_parser)->i_bool_items;
956 p_longopts = malloc( sizeof(struct option) * (i_opts + 1) );
957 if( p_longopts == NULL )
959 msg_Err( p_this, "out of memory" );
960 vlc_list_release( p_list );
964 psz_shortopts = malloc( sizeof( char ) * (2 * i_opts + 1) );
965 if( psz_shortopts == NULL )
967 msg_Err( p_this, "out of memory" );
969 vlc_list_release( p_list );
973 /* If we are requested to ignore errors, then we must work on a copy
974 * of the ppsz_argv array, otherwise getopt_long will reorder it for
975 * us, ignoring the arity of the options */
976 if( b_ignore_errors )
978 ppsz_argv = (char**)malloc( *pi_argc * sizeof(char *) );
979 if( ppsz_argv == NULL )
981 msg_Err( p_this, "out of memory" );
982 free( psz_shortopts );
984 vlc_list_release( p_list );
987 memcpy( ppsz_argv, p_this->p_vlc->ppsz_argv,
988 *pi_argc * sizeof(char *) );
992 for( i_index = 0; i_index < 256; i_index++ )
994 pp_shortopts[i_index] = NULL;
997 /* Fill the p_longopts and psz_shortopts structures */
999 for( pp_parser = (module_t **)p_list->pp_objects ;
1003 if( !(*pp_parser)->i_config_items )
1006 for( p_item = (*pp_parser)->p_config;
1007 p_item->i_type != CONFIG_HINT_END;
1011 if( p_item->i_type & CONFIG_HINT )
1014 /* Add item to long options */
1015 p_longopts[i_index].name = strdup( p_item->psz_name );
1016 if( p_longopts[i_index].name == NULL ) continue;
1017 p_longopts[i_index].has_arg =
1018 (p_item->i_type == CONFIG_ITEM_BOOL)?
1019 no_argument : required_argument;
1020 p_longopts[i_index].flag = &flag;
1021 p_longopts[i_index].val = 0;
1024 /* When dealing with bools we also need to add the --no-foo
1026 if( p_item->i_type == CONFIG_ITEM_BOOL )
1028 char *psz_name = malloc( strlen(p_item->psz_name) + 3 );
1029 if( psz_name == NULL ) continue;
1030 strcpy( psz_name, "no" );
1031 strcat( psz_name, p_item->psz_name );
1033 p_longopts[i_index].name = psz_name;
1034 p_longopts[i_index].has_arg = no_argument;
1035 p_longopts[i_index].flag = &flag;
1036 p_longopts[i_index].val = 1;
1039 psz_name = malloc( strlen(p_item->psz_name) + 4 );
1040 if( psz_name == NULL ) continue;
1041 strcpy( psz_name, "no-" );
1042 strcat( psz_name, p_item->psz_name );
1044 p_longopts[i_index].name = psz_name;
1045 p_longopts[i_index].has_arg = no_argument;
1046 p_longopts[i_index].flag = &flag;
1047 p_longopts[i_index].val = 1;
1051 /* If item also has a short option, add it */
1052 if( p_item->i_short )
1054 pp_shortopts[(int)p_item->i_short] = p_item;
1055 psz_shortopts[i_shortopts] = p_item->i_short;
1057 if( p_item->i_type != CONFIG_ITEM_BOOL )
1059 psz_shortopts[i_shortopts] = ':';
1062 if( p_item->i_short == 'v' )
1064 psz_shortopts[i_shortopts] = ':';
1072 /* We don't need the module list anymore */
1073 vlc_list_release( p_list );
1075 /* Close the longopts and shortopts structures */
1076 memset( &p_longopts[i_index], 0, sizeof(struct option) );
1077 psz_shortopts[i_shortopts] = '\0';
1080 * Parse the command line options
1084 while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
1085 p_longopts, &i_index ) ) != EOF )
1087 /* A long option has been recognized */
1090 module_config_t *p_conf;
1091 char *psz_name = (char *)p_longopts[i_index].name;
1093 /* Check if we deal with a --nofoo or --no-foo long option */
1094 if( flag ) psz_name += psz_name[2] == '-' ? 3 : 2;
1096 /* Store the configuration option */
1097 p_conf = config_FindConfig( p_this, psz_name );
1099 if( p_conf ) switch( p_conf->i_type )
1101 case CONFIG_ITEM_STRING:
1102 case CONFIG_ITEM_FILE:
1103 case CONFIG_ITEM_MODULE:
1104 config_PutPsz( p_this, psz_name, optarg );
1106 case CONFIG_ITEM_INTEGER:
1107 config_PutInt( p_this, psz_name, atoi(optarg));
1109 case CONFIG_ITEM_FLOAT:
1110 config_PutFloat( p_this, psz_name, (float)atof(optarg) );
1112 case CONFIG_ITEM_BOOL:
1113 config_PutInt( p_this, psz_name, !flag );
1120 /* A short option has been recognized */
1121 if( pp_shortopts[i_cmd] != NULL )
1123 switch( pp_shortopts[i_cmd]->i_type )
1125 case CONFIG_ITEM_STRING:
1126 case CONFIG_ITEM_FILE:
1127 case CONFIG_ITEM_MODULE:
1128 config_PutPsz( p_this, pp_shortopts[i_cmd]->psz_name, optarg );
1130 case CONFIG_ITEM_INTEGER:
1135 if( *optarg == 'v' ) /* eg. -vvv */
1138 while( *optarg == 'v' )
1146 i_verbose += atoi( optarg ); /* eg. -v2 */
1151 i_verbose++; /* -v */
1153 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1158 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name,
1162 case CONFIG_ITEM_BOOL:
1163 config_PutInt( p_this, pp_shortopts[i_cmd]->psz_name, 1 );
1170 /* Internal error: unknown option */
1171 if( !b_ignore_errors )
1173 fprintf( stderr, "unknown option `%s'\n", ppsz_argv[optind-1] );
1174 fprintf( stderr, "Try `%s --help' for more information.\n",
1175 p_this->p_vlc->psz_object_name );
1178 free( psz_shortopts );
1179 if( b_ignore_errors ) free( ppsz_argv );
1184 /* Free allocated resources */
1185 for( i_index = 0; p_longopts[i_index].name; i_index++ )
1186 free( (char *)p_longopts[i_index].name );
1188 free( psz_shortopts );
1189 if( b_ignore_errors ) free( ppsz_argv );
1194 /*****************************************************************************
1195 * config_GetHomeDir: find the user's home directory.
1196 *****************************************************************************
1197 * This function will try by different ways to find the user's home path.
1198 * Note that this function is not reentrant, it should be called only once
1199 * at the beginning of main where the result will be stored for later use.
1200 *****************************************************************************/
1201 char *config_GetHomeDir( void )
1203 char *p_tmp, *p_homedir = NULL;
1205 #if defined(HAVE_GETPWUID)
1206 struct passwd *p_pw = NULL;
1210 typedef HRESULT (WINAPI *SHGETFOLDERPATH)( HWND, int, HANDLE, DWORD,
1212 # define CSIDL_FLAG_CREATE 0x8000
1213 # define CSIDL_APPDATA 0x1A
1214 # define SHGFP_TYPE_CURRENT 0
1216 HINSTANCE shfolder_dll;
1217 SHGETFOLDERPATH SHGetFolderPath ;
1219 /* load the shell32 dll to retreive SHGetFolderPath */
1220 if( ( shfolder_dll = LoadLibrary("shfolder.dll") ) != NULL )
1222 SHGetFolderPath = (void *)GetProcAddress( shfolder_dll,
1223 "SHGetFolderPathA" );
1224 if ( SHGetFolderPath != NULL )
1226 p_homedir = (char *)malloc( MAX_PATH );
1232 /* get the "Application Data" folder for the current user */
1233 if( S_OK == SHGetFolderPath( NULL,
1234 CSIDL_APPDATA | CSIDL_FLAG_CREATE,
1235 NULL, SHGFP_TYPE_CURRENT,
1238 FreeLibrary( shfolder_dll );
1243 FreeLibrary( shfolder_dll );
1247 #if defined(HAVE_GETPWUID)
1248 if( ( p_pw = getpwuid( getuid() ) ) == NULL )
1251 if( ( p_tmp = getenv( "HOME" ) ) == NULL )
1253 if( ( p_tmp = getenv( "TMP" ) ) == NULL )
1259 p_homedir = strdup( p_tmp );
1261 #if defined(HAVE_GETPWUID)
1264 p_homedir = strdup( p_pw->pw_dir );