]> git.sesse.net Git - vlc/blob - src/misc/configuration.c
* ./AUTHORS: added people locations, just for fun.
[vlc] / src / misc / configuration.c
1 /*****************************************************************************
2  * configuration.c management of the modules configuration
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: configuration.c,v 1.14 2002/04/17 11:43:31 sam Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <videolan/vlc.h>
25
26 #include <stdio.h>                                              /* sprintf() */
27 #include <stdlib.h>                                      /* free(), strtol() */
28 #include <string.h>                                              /* strdup() */
29 #include <errno.h>                                                 /* errno */
30
31 #ifdef HAVE_UNISTD_H
32 #    include <unistd.h>                                          /* getuid() */
33 #endif
34
35 #ifdef HAVE_GETOPT_LONG
36 #   ifdef HAVE_GETOPT_H
37 #       include <getopt.h>                                       /* getopt() */
38 #   endif
39 #else
40 #   include "GNUgetopt/getopt.h"
41 #endif
42
43 #if defined(HAVE_GETPWUID)
44 #include <pwd.h>                                               /* getpwuid() */
45 #endif
46
47 #include <sys/stat.h>
48 #include <sys/types.h>
49
50 /*****************************************************************************
51  * config_GetIntVariable: get the value of an int variable
52  *****************************************************************************
53  * This function is used to get the value of variables which are internally
54  * represented by an integer (MODULE_CONFIG_ITEM_INTEGER and
55  * MODULE_CONFIG_ITEM_BOOL).
56  *****************************************************************************/
57 int config_GetIntVariable( const char *psz_name )
58 {
59     module_config_t *p_config;
60
61     p_config = config_FindConfig( psz_name );
62
63     /* sanity checks */
64     if( !p_config )
65     {
66         intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
67         return -1;
68     }
69     if( (p_config->i_type!=MODULE_CONFIG_ITEM_INTEGER) &&
70         (p_config->i_type!=MODULE_CONFIG_ITEM_BOOL) )
71     {
72         intf_ErrMsg( "config error: option %s doesn't refer to an int",
73                      psz_name );
74         return -1;
75     }
76
77     return p_config->i_value;
78 }
79
80 /*****************************************************************************
81  * config_GetPszVariable: get the string value of a string variable
82  *****************************************************************************
83  * This function is used to get the value of variables which are internally
84  * represented by a string (MODULE_CONFIG_ITEM_STRING, MODULE_CONFIG_ITEM_FILE,
85  * and MODULE_CONFIG_ITEM_PLUGIN).
86  *
87  * Important note: remember to free() the returned char* because it a duplicate
88  *   of the actual value. It isn't safe to return a pointer to the actual value
89  *   as it can be modified at any time.
90  *****************************************************************************/
91 char * config_GetPszVariable( const char *psz_name )
92 {
93     module_config_t *p_config;
94     char *psz_value = NULL;
95
96     p_config = config_FindConfig( psz_name );
97
98     /* sanity checks */
99     if( !p_config )
100     {
101         intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
102         return NULL;
103     }
104     if( (p_config->i_type!=MODULE_CONFIG_ITEM_STRING) &&
105         (p_config->i_type!=MODULE_CONFIG_ITEM_FILE) &&
106         (p_config->i_type!=MODULE_CONFIG_ITEM_PLUGIN) )
107     {
108         intf_ErrMsg( "config error: option %s doesn't refer to a string",
109                      psz_name );
110         return NULL;
111     }
112
113     /* return a copy of the string */
114     vlc_mutex_lock( p_config->p_lock );
115     if( p_config->psz_value ) psz_value = strdup( p_config->psz_value );
116     vlc_mutex_unlock( p_config->p_lock );
117
118     return psz_value;
119 }
120
121 /*****************************************************************************
122  * config_PutPszVariable: set the string value of a string variable
123  *****************************************************************************
124  * This function is used to set the value of variables which are internally
125  * represented by a string (MODULE_CONFIG_ITEM_STRING, MODULE_CONFIG_ITEM_FILE,
126  * and MODULE_CONFIG_ITEM_PLUGIN).
127  *****************************************************************************/
128 void config_PutPszVariable( const char *psz_name, char *psz_value )
129 {
130     module_config_t *p_config;
131
132     p_config = config_FindConfig( psz_name );
133
134     /* sanity checks */
135     if( !p_config )
136     {
137         intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
138         return;
139     }
140     if( (p_config->i_type!=MODULE_CONFIG_ITEM_STRING) &&
141         (p_config->i_type!=MODULE_CONFIG_ITEM_FILE) &&
142         (p_config->i_type!=MODULE_CONFIG_ITEM_PLUGIN) )
143     {
144         intf_ErrMsg( "config error: option %s doesn't refer to a string",
145                      psz_name );
146         return;
147     }
148
149     vlc_mutex_lock( p_config->p_lock );
150
151     /* free old string */
152     if( p_config->psz_value ) free( p_config->psz_value );
153
154     if( psz_value ) p_config->psz_value = strdup( psz_value );
155     else p_config->psz_value = NULL;
156
157     vlc_mutex_unlock( p_config->p_lock );
158
159 }
160
161 /*****************************************************************************
162  * config_PutIntVariable: set the integer value of an int variable
163  *****************************************************************************
164  * This function is used to set the value of variables which are internally
165  * represented by an integer (MODULE_CONFIG_ITEM_INTEGER and
166  * MODULE_CONFIG_ITEM_BOOL).
167  *****************************************************************************/
168 void config_PutIntVariable( const char *psz_name, int i_value )
169 {
170     module_config_t *p_config;
171
172     p_config = config_FindConfig( psz_name );
173
174     /* sanity checks */
175     if( !p_config )
176     {
177         intf_ErrMsg( "config error: option %s doesn't exist", psz_name );
178         return;
179     }
180     if( (p_config->i_type!=MODULE_CONFIG_ITEM_INTEGER) &&
181         (p_config->i_type!=MODULE_CONFIG_ITEM_BOOL) )
182     {
183         intf_ErrMsg( "config error: option %s doesn't refer to an int",
184                      psz_name );
185         return;
186     }
187
188     p_config->i_value = i_value;
189 }
190
191 /*****************************************************************************
192  * config_FindConfig: find the config structure associated with an option.
193  *****************************************************************************
194  * FIXME: This function really needs to be optimized.
195  *****************************************************************************/
196 module_config_t *config_FindConfig( const char *psz_name )
197 {
198     module_t *p_module;
199     int i;
200
201     if( !psz_name ) return NULL;
202
203     for( p_module = p_module_bank->first ;
204          p_module != NULL ;
205          p_module = p_module->next )
206     {
207         for( i = 0; i < p_module->i_config_lines; i++ )
208         {
209             if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
210                 /* ignore hints */
211                 continue;
212             if( !strcmp( psz_name, p_module->p_config[i].psz_name ) )
213                 return &p_module->p_config[i];
214         }
215     }
216
217     return NULL;
218 }
219
220 /*****************************************************************************
221  * config_Duplicate: creates a duplicate of a module's configuration data.
222  *****************************************************************************
223  * Unfortunatly we cannot work directly with the module's config data as
224  * this module might be unloaded from memory at any time (remember HideModule).
225  * This is why we need to create an exact copy of the config data.
226  *****************************************************************************/
227 module_config_t *config_Duplicate( module_t *p_module )
228 {
229     int i;
230     module_config_t *p_config;
231
232     /* allocate memory */
233     p_config = (module_config_t *)malloc( sizeof(module_config_t)
234                                           * p_module->i_config_lines );
235     if( p_config == NULL )
236     {
237         intf_ErrMsg( "config error: can't duplicate p_config" );
238         return( NULL );
239     }
240
241     for( i = 0; i < p_module->i_config_lines ; i++ )
242     {
243         p_config[i].i_type = p_module->p_config_orig[i].i_type;
244         p_config[i].i_value = p_module->p_config_orig[i].i_value;
245         p_config[i].b_dirty = p_module->p_config_orig[i].b_dirty;
246         p_config[i].p_lock = &p_module->config_lock;
247         if( p_module->p_config_orig[i].psz_name )
248             p_config[i].psz_name =
249                 strdup( p_module->p_config_orig[i].psz_name );
250         else p_config[i].psz_name = NULL;
251         if( p_module->p_config_orig[i].psz_text )
252             p_config[i].psz_text =
253                 strdup( p_module->p_config_orig[i].psz_text );
254         else p_config[i].psz_text = NULL;
255         if( p_module->p_config_orig[i].psz_longtext )
256             p_config[i].psz_longtext =
257                 strdup( p_module->p_config_orig[i].psz_longtext );
258         else p_config[i].psz_longtext = NULL;
259         if( p_module->p_config_orig[i].psz_value )
260             p_config[i].psz_value =
261                 strdup( p_module->p_config_orig[i].psz_value );
262         else p_config[i].psz_value = NULL;
263
264         /* the callback pointer is only valid when the module is loaded so this
265          * value is set in ActivateModule() and reset in DeactivateModule() */
266         p_config[i].p_callback = NULL;
267     }
268
269     return p_config;
270 }
271
272 /*****************************************************************************
273  * config_LoadConfigFile: loads the configuration file.
274  *****************************************************************************
275  * This function is called to load the config options stored in the config
276  * file.
277  *****************************************************************************/
278 int config_LoadConfigFile( const char *psz_module_name )
279 {
280     module_t *p_module;
281     FILE *file;
282     char line[1024];
283     char *p_index, *psz_option_name, *psz_option_value;
284     int i;
285     char *psz_filename, *psz_homedir;
286
287     /* Acquire config file lock */
288     vlc_mutex_lock( &p_main->config_lock );
289
290     psz_homedir = p_main->psz_homedir;
291     if( !psz_homedir )
292     {
293         intf_ErrMsg( "config error: p_main->psz_homedir is null" );
294         vlc_mutex_unlock( &p_main->config_lock );
295         return -1;
296     }
297     psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
298                                    strlen(psz_homedir) + 1 );
299     if( !psz_filename )
300     {
301         intf_ErrMsg( "config error: couldn't malloc psz_filename" );
302         vlc_mutex_unlock( &p_main->config_lock );
303         return -1;
304     }
305     sprintf( psz_filename, "%s/" CONFIG_DIR "/" CONFIG_FILE, psz_homedir );
306
307     intf_WarnMsg( 5, "config: opening config file %s", psz_filename );
308
309     file = fopen( psz_filename, "r" );
310     if( !file )
311     {
312         intf_WarnMsg( 1, "config: couldn't open config file %s for reading (%s)",
313                          psz_filename, strerror(errno) );
314         free( psz_filename );
315         vlc_mutex_unlock( &p_main->config_lock );
316         return -1;
317     }
318
319     /* Look for the selected module, if NULL then save everything */
320     for( p_module = p_module_bank->first ; p_module != NULL ;
321          p_module = p_module->next )
322     {
323
324         if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
325             continue;
326
327         /* The config file is organized in sections, one per module. Look for
328          * the interesting section ( a section is of the form [foo] ) */
329         rewind( file );
330         while( fgets( line, 1024, file ) )
331         {
332             if( (line[0] == '[') && (p_index = strchr(line,']')) &&
333                 (p_index - &line[1] == strlen(p_module->psz_name) ) &&
334                 !memcmp( &line[1], p_module->psz_name,
335                          strlen(p_module->psz_name) ) )
336             {
337                 intf_WarnMsg( 5, "config: loading config for module <%s>",
338                                  p_module->psz_name );
339
340                 break;
341             }
342         }
343         /* either we found the section or we're at the EOF */
344
345         /* Now try to load the options in this section */
346         while( fgets( line, 1024, file ) )
347         {
348             if( line[0] == '[' ) break; /* end of section */
349
350             /* ignore comments or empty lines */
351             if( (line[0] == '#') || (line[0] == (char)0) ) continue;
352
353             /* get rid of line feed */
354             if( line[strlen(line)-1] == '\n' )
355                 line[strlen(line)-1] = (char)0;
356
357             /* look for option name */
358             psz_option_name = line;
359             psz_option_value = NULL;
360             p_index = strchr( line, '=' );
361             if( !p_index ) break; /* this ain't an option!!! */
362
363             *p_index = (char)0;
364             psz_option_value = p_index + 1;
365
366             /* try to match this option with one of the module's options */
367             for( i = 0; i < p_module->i_config_lines; i++ )
368             {
369                 if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
370                     /* ignore hints */
371                     continue;
372                 if( !strcmp( p_module->p_config[i].psz_name,
373                              psz_option_name ) )
374                 {
375                     /* We found it */
376                     switch( p_module->p_config[i].i_type )
377                     {
378                     case MODULE_CONFIG_ITEM_BOOL:
379                     case MODULE_CONFIG_ITEM_INTEGER:
380                         if( !*psz_option_value )
381                             break;                    /* ignore empty option */
382                         p_module->p_config[i].i_value =
383                             atoi( psz_option_value);
384                         intf_WarnMsg( 7, "config: found <%s> option %s=%i",
385                                       p_module->psz_name,
386                                       p_module->p_config[i].psz_name,
387                                       p_module->p_config[i].i_value );
388                         break;
389
390                     default:
391                         vlc_mutex_lock( p_module->p_config[i].p_lock );
392
393                         /* free old string */
394                         if( p_module->p_config[i].psz_value )
395                             free( p_module->p_config[i].psz_value );
396
397                         p_module->p_config[i].psz_value = *psz_option_value ?
398                             strdup( psz_option_value ) : NULL;
399
400                         vlc_mutex_unlock( p_module->p_config[i].p_lock );
401
402                         intf_WarnMsg( 7, "config: found <%s> option %s=%s",
403                                       p_module->psz_name,
404                                       p_module->p_config[i].psz_name,
405                                       p_module->p_config[i].psz_value != NULL ?
406                                         p_module->p_config[i].psz_value :
407                                         "(NULL)" );
408                         break;
409                     }
410                 }
411             }
412         }
413
414     }
415     
416     fclose( file );
417     free( psz_filename );
418
419     vlc_mutex_unlock( &p_main->config_lock );
420
421     return 0;
422 }
423
424 /*****************************************************************************
425  * config_SaveConfigFile: Save a module's config options.
426  *****************************************************************************
427  * This will save the specified module's config options to the config file.
428  * If psz_module_name is NULL then we save all the modules config options.
429  * It's no use to save the config options that kept their default values, so
430  * we'll try to be a bit clever here.
431  *
432  * When we save we mustn't delete the config options of the plugins that
433  * haven't been loaded. So we cannot just create a new config file with the
434  * config structures we've got in memory. 
435  * I don't really know how to deal with this nicely, so I will use a completly
436  * dumb method ;-)
437  * I will load the config file in memory, but skipping all the sections of the
438  * modules we want to save. Then I will create a brand new file, dump the file
439  * loaded in memory and then append the sections of the modules we want to
440  * save.
441  * Really stupid no ?
442  *****************************************************************************/
443 int config_SaveConfigFile( const char *psz_module_name )
444 {
445     module_t *p_module;
446     FILE *file;
447     char p_line[1024], *p_index2;
448     int i, i_sizebuf = 0;
449     char *p_bigbuffer, *p_index;
450     boolean_t b_backup;
451     char *psz_filename, *psz_homedir;
452
453     /* Acquire config file lock */
454     vlc_mutex_lock( &p_main->config_lock );
455
456     psz_homedir = p_main->psz_homedir;
457     if( !psz_homedir )
458     {
459         intf_ErrMsg( "config error: p_main->psz_homedir is null" );
460         vlc_mutex_unlock( &p_main->config_lock );
461         return -1;
462     }
463     psz_filename = (char *)malloc( strlen("/" CONFIG_DIR "/" CONFIG_FILE) +
464                                    strlen(psz_homedir) + 1 );
465     if( !psz_filename )
466     {
467         intf_ErrMsg( "config error: couldn't malloc psz_filename" );
468         vlc_mutex_unlock( &p_main->config_lock );
469         return -1;
470     }
471     sprintf( psz_filename, "%s/" CONFIG_DIR, psz_homedir );
472 #ifndef WIN32
473     i = mkdir( psz_filename, 0755 );
474 #else
475     i = mkdir( psz_filename );
476 #endif
477     if( i && errno != EEXIST )
478     {
479         intf_ErrMsg( "config error: couldn't create %s (%s)",
480                      psz_filename, strerror(errno) );
481     }
482
483     strcat( psz_filename, "/" CONFIG_FILE );
484
485
486     intf_WarnMsg( 5, "config: opening config file %s", psz_filename );
487
488     file = fopen( psz_filename, "r" );
489     if( !file )
490     {
491         intf_WarnMsg( 1, "config: couldn't open config file %s for reading (%s)",
492                          psz_filename, strerror(errno) );
493     }
494     else
495     {
496         /* look for file size */
497         fseek( file, 0, SEEK_END );
498         i_sizebuf = ftell( file );
499         rewind( file );
500     }
501
502     p_bigbuffer = p_index = malloc( i_sizebuf+1 );
503     if( !p_bigbuffer )
504     {
505         intf_ErrMsg( "config error: couldn't malloc bigbuffer" );
506         if( file ) fclose( file );
507         free( psz_filename );
508         vlc_mutex_unlock( &p_main->config_lock );
509         return -1;
510     }
511     p_bigbuffer[0] = 0;
512
513     /* backup file into memory, we only need to backup the sections we won't
514      * save later on */
515     b_backup = 0;
516     while( file && fgets( p_line, 1024, file ) )
517     {
518         if( (p_line[0] == '[') && (p_index2 = strchr(p_line,']')))
519         {
520             /* we found a section, check if we need to do a backup */
521             for( p_module = p_module_bank->first; p_module != NULL;
522                  p_module = p_module->next )
523             {
524                 if( ((p_index2 - &p_line[1]) == strlen(p_module->psz_name) ) &&
525                     !memcmp( &p_line[1], p_module->psz_name,
526                              strlen(p_module->psz_name) ) )
527                 {
528                     if( !psz_module_name )
529                         break;
530                     else if( !strcmp( psz_module_name, p_module->psz_name ) )
531                         break;
532                 }
533             }
534
535             if( !p_module )
536             {
537                 /* we don't have this section in our list so we need to back
538                  * it up */
539                 *p_index2 = 0;
540                 intf_WarnMsg( 5, "config: backing up config for "
541                                  "unknown module <%s>", &p_line[1] );
542                 *p_index2 = ']';
543
544                 b_backup = 1;
545             }
546             else
547             {
548                 b_backup = 0;
549             }
550         }
551
552         /* save line if requested and line is valid (doesn't begin with a
553          * space, tab, or eol) */
554         if( b_backup && (p_line[0] != '\n') && (p_line[0] != ' ')
555             && (p_line[0] != '\t') )
556         {
557             strcpy( p_index, p_line );
558             p_index += strlen( p_line );
559         }
560     }
561     if( file ) fclose( file );
562
563
564     /*
565      * Save module config in file
566      */
567
568     file = fopen( psz_filename, "w" );
569     if( !file )
570     {
571         intf_WarnMsg( 1, "config: couldn't open config file %s for writing",
572                          psz_filename );
573         free( psz_filename );
574         vlc_mutex_unlock( &p_main->config_lock );
575         return -1;
576     }
577
578     fprintf( file, "###\n###  " COPYRIGHT_MESSAGE "\n###\n\n" );
579
580     /* Look for the selected module, if NULL then save everything */
581     for( p_module = p_module_bank->first ; p_module != NULL ;
582          p_module = p_module->next )
583     {
584
585         if( psz_module_name && strcmp( psz_module_name, p_module->psz_name ) )
586             continue;
587
588         if( !p_module->i_config_items )
589             continue;
590
591         intf_WarnMsg( 5, "config: saving config for module <%s>",
592                          p_module->psz_name );
593
594         fprintf( file, "[%s]\n", p_module->psz_name );
595
596         if( p_module->psz_longname )
597             fprintf( file, "###\n###  %s\n###\n", p_module->psz_longname );
598
599         for( i = 0; i < p_module->i_config_lines; i++ )
600         {
601             if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
602                 /* ignore hints */
603                 continue;
604
605             switch( p_module->p_config[i].i_type )
606             {
607             case MODULE_CONFIG_ITEM_BOOL:
608             case MODULE_CONFIG_ITEM_INTEGER:
609                 if( p_module->p_config[i].psz_text )
610                     fprintf( file, "# %s %s\n", p_module->p_config[i].psz_text,
611                              MODULE_CONFIG_ITEM_BOOL?"<boolean>":"<integer>" );
612                 fprintf( file, "%s=%i\n", p_module->p_config[i].psz_name,
613                          p_module->p_config[i].i_value );
614                 break;
615
616             default:
617                 if( p_module->p_config[i].psz_text )
618                     fprintf( file, "# %s <string>\n",
619                              p_module->p_config[i].psz_text );
620                 fprintf( file, "%s=%s\n", p_module->p_config[i].psz_name,
621                          p_module->p_config[i].psz_value?
622                          p_module->p_config[i].psz_value:"" );
623             }
624         }
625
626         fprintf( file, "\n" );
627     }
628
629
630     /*
631      * Restore old settings from the config in file
632      */
633     fputs( p_bigbuffer, file );
634     free( p_bigbuffer );
635
636     fclose( file );
637     free( psz_filename );
638     vlc_mutex_unlock( &p_main->config_lock );
639
640     return 0;
641 }
642
643 /*****************************************************************************
644  * config_LoadCmdLine: parse command line
645  *****************************************************************************
646  * Parse command line for configuration options.
647  * Now that the module_bank has been initialized, we can dynamically
648  * generate the longopts structure used by getops. We have to do it this way
649  * because we don't know (and don't want to know) in advance the configuration
650  * options used (ie. exported) by each module.
651  *****************************************************************************/
652 int config_LoadCmdLine( int *pi_argc, char *ppsz_argv[],
653                         boolean_t b_ignore_errors )
654 {
655     int i_cmd, i, i_index, i_longopts_size;
656     module_t *p_module;
657     struct option *p_longopts;
658
659     /* Short options */
660     const char *psz_shortopts = "hHvlp:";
661
662     /* Set default configuration and copy arguments */
663     p_main->i_argc    = *pi_argc;
664     p_main->ppsz_argv = ppsz_argv;
665
666     p_main->p_channel = NULL;
667
668 #ifdef SYS_DARWIN
669     /* When vlc.app is run by double clicking in Mac OS X, the 2nd arg
670      * is the PSN - process serial number (a unique PID-ish thingie)
671      * still ok for real Darwin & when run from command line */
672     if ( (*pi_argc > 1) && (strncmp( ppsz_argv[ 1 ] , "-psn" , 4 ) == 0) )
673                                         /* for example -psn_0_9306113 */
674     {
675         /* GDMF!... I can't do this or else the MacOSX window server will
676          * not pick up the PSN and not register the app and we crash...
677          * hence the following kludge otherwise we'll get confused w/ argv[1]
678          * being an input file name */
679 #if 0
680         ppsz_argv[ 1 ] = NULL;
681 #endif
682         *pi_argc = *pi_argc - 1;
683         pi_argc--;
684         return( 0 );
685     }
686 #endif
687
688
689     /*
690      * Generate the longopts structure used by getopt_long
691      */
692     i_longopts_size = 0;
693     for( p_module = p_module_bank->first;
694          p_module != NULL ;
695          p_module = p_module->next )
696     {
697         /* count the number of exported configuration options (to allocate
698          * longopts). */
699         i_longopts_size += p_module->i_config_items;
700     }
701
702     p_longopts = (struct option *)malloc( sizeof(struct option)
703                                           * (i_longopts_size + 1) );
704     if( p_longopts == NULL )
705     {
706         intf_ErrMsg( "config error: couldn't allocate p_longopts" );
707         return( -1 );
708     }
709
710     /* Fill the longopts structure */
711     i_index = 0;
712     for( p_module = p_module_bank->first ;
713          p_module != NULL ;
714          p_module = p_module->next )
715     {
716         for( i = 0; i < p_module->i_config_lines; i++ )
717         {
718             if( p_module->p_config[i].i_type & MODULE_CONFIG_HINT )
719                 /* ignore hints */
720                 continue;
721             p_longopts[i_index].name = p_module->p_config[i].psz_name;
722             p_longopts[i_index].has_arg =
723                 (p_module->p_config[i].i_type == MODULE_CONFIG_ITEM_BOOL)?
724                                                no_argument : required_argument;
725             p_longopts[i_index].flag = 0;
726             p_longopts[i_index].val = 0;
727             i_index++;
728         }
729     }
730     /* Close the longopts structure */
731     memset( &p_longopts[i_index], 0, sizeof(struct option) );
732
733
734     /*
735      * Parse the command line options
736      */
737     opterr = 0;
738     optind = 1;
739     while( ( i_cmd = getopt_long( *pi_argc, ppsz_argv, psz_shortopts,
740                                   p_longopts, &i_index ) ) != EOF )
741     {
742
743         if( i_cmd == 0 )
744         {
745             /* A long option has been recognized */
746
747             module_config_t *p_conf;
748
749             /* Store the configuration option */
750             p_conf = config_FindConfig( p_longopts[i_index].name );
751
752             switch( p_conf->i_type )
753             {
754             case MODULE_CONFIG_ITEM_STRING:
755             case MODULE_CONFIG_ITEM_FILE:
756             case MODULE_CONFIG_ITEM_PLUGIN:
757                 config_PutPszVariable( p_longopts[i_index].name, optarg );
758                 break;
759             case MODULE_CONFIG_ITEM_INTEGER:
760                 config_PutIntVariable( p_longopts[i_index].name, atoi(optarg));
761                 break;
762             case MODULE_CONFIG_ITEM_BOOL:
763                 config_PutIntVariable( p_longopts[i_index].name, 1 );
764                 break;
765             }
766
767             continue;
768         }
769
770         /* short options handled here for now */
771         switch( i_cmd )
772         {
773
774         /* General/common options */
775         case 'h':                                              /* -h, --help */
776             config_PutIntVariable( "help", 1 );
777             break;
778         case 'H':                                          /* -H, --longhelp */
779             config_PutIntVariable( "longhelp", 1 );
780             break;
781         case 'l':                                              /* -l, --list */
782             config_PutIntVariable( "list", 1 );
783             break;
784         case 'p':                                            /* -p, --plugin */
785             config_PutPszVariable( "plugin", optarg );
786             break;
787         case 'v':                                           /* -v, --verbose */
788             p_main->i_warning_level++;
789             break;
790
791         /* Internal error: unknown option */
792         case '?':
793         default:
794
795             if( !b_ignore_errors )
796             {
797                 intf_ErrMsg( "config error: unknown option `%s'",
798                              ppsz_argv[optind-1] );
799                 intf_Msg( "Try `%s --help' for more information.\n",
800                           p_main->psz_arg0 );
801
802                 free( p_longopts );
803                 return( -1 );
804             }
805         }
806
807     }
808
809     if( p_main->i_warning_level < 0 )
810     {
811         p_main->i_warning_level = 0;
812     }
813
814     free( p_longopts );
815     return( 0 );
816 }
817
818 /*****************************************************************************
819  * config_GetHomeDir: find the user's home directory.
820  *****************************************************************************
821  * This function will try by different ways to find the user's home path.
822  * Note that this function is not reentrant, it should be called only once
823  * at the beginning of main where the result will be stored for later use.
824  *****************************************************************************/
825 char *config_GetHomeDir( void )
826 {
827     char *p_tmp, *p_homedir = NULL;
828
829 #if defined(HAVE_GETPWUID)
830     struct passwd *p_pw = NULL;
831 #endif
832
833 #if defined(HAVE_GETPWUID)
834     if( ( p_pw = getpwuid( getuid() ) ) == NULL )
835 #endif
836     {
837         if( ( p_tmp = getenv( "HOME" ) ) == NULL )
838         {
839             if( ( p_tmp = getenv( "TMP" ) ) == NULL )
840             {
841                 p_homedir = strdup( "/tmp" );
842             }
843             else p_homedir = strdup( p_tmp );
844
845             intf_ErrMsg( "config error: unable to get home directory, "
846                          "using %s instead", p_homedir );
847
848         }
849         else p_homedir = strdup( p_tmp );
850     }
851 #if defined(HAVE_GETPWUID)
852     else
853     {
854         p_homedir = strdup( p_pw->pw_dir );
855     }
856 #endif
857
858     return p_homedir;
859 }