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