+ /* Open file */
+ p_file = fopen( psz_filename, "r" );
+ if( p_file == NULL )
+ {
+ intf_ErrMsg("error: can't open %s (%s)\n", psz_filename, strerror(errno));
+ return( 1 );
+ }
+
+ /* First pass: count number of lines */
+ for( i_index = 0; fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL; i_index++ )
+ {
+ ;
+ }
+
+ if( i_index != 0 )
+ {
+ /* Allocate array and rewind - some of the lines may be invalid, and the
+ * array will probably be larger than the actual number of channels, but
+ * it has no consequence. */
+ p_intf->p_channel = malloc( sizeof( intf_channel_t ) * i_index );
+ if( p_intf->p_channel == NULL )
+ {
+ intf_ErrMsg("error: %s\n", strerror(ENOMEM));
+ fclose( p_file );
+ return( 1 );
+ }
+ p_channel = p_intf->p_channel;
+ rewind( p_file );
+
+ /* Second pass: read channels descriptions */
+ while( fgets( psz_line, INTF_MAX_CMD_SIZE, p_file ) != NULL )
+ {
+ if( !ParseChannel( p_channel, psz_line ) )
+ {
+ intf_DbgMsg("channel [%d] %s : method %d (%s:%d vlan %d)\n",
+ p_channel->i_channel, p_channel->psz_description,
+ p_channel->i_input_method, p_channel->psz_input_source,
+ p_channel->i_input_port, p_channel->i_input_vlan );
+ p_channel++;
+ }
+ }
+
+ /* Add marker at the end of the array */
+ p_channel->i_channel = -1;
+ }
+
+ /* Close file */
+ fclose( p_file );
+ return( 0 );
+}
+
+/*****************************************************************************
+ * UnloadChannels: unload channels description
+ *****************************************************************************
+ * This function free all resources allocated by LoadChannels, if any.
+ *****************************************************************************/
+static void UnloadChannels( intf_thread_t *p_intf )
+{
+ int i_channel; /* channel index */
+
+ if( p_intf->p_channel != NULL )
+ {
+ /* Free allocated strings */
+ for( i_channel = 0;
+ p_intf->p_channel[ i_channel ].i_channel != -1;
+ i_channel++ )
+ {
+ if( p_intf->p_channel[ i_channel ].psz_description != NULL )
+ {
+ free( p_intf->p_channel[ i_channel ].psz_description );
+ }
+ if( p_intf->p_channel[ i_channel ].psz_input_source != NULL )
+ {
+ free( p_intf->p_channel[ i_channel ].psz_input_source );
+ }
+ }
+
+ /* Free array */
+ free( p_intf->p_channel );
+ p_intf->p_channel = NULL;
+ }
+}
+
+
+/*****************************************************************************
+ * ParseChannel: parse a channel description line
+ *****************************************************************************
+ * See LoadChannels. This function return non 0 on parsing error.
+ *****************************************************************************/
+static int ParseChannel( intf_channel_t *p_channel, char *psz_str )
+{
+ char * psz_index; /* current character */
+ char * psz_end; /* end pointer for strtol */
+ int i_field; /* field number, -1 on error */
+ int i_field_length; /* field length, for text fields */
+
+ /* Set some default fields */
+ p_channel->i_channel = 0;
+ p_channel->psz_description = NULL;
+ p_channel->i_input_method = 0;
+ p_channel->psz_input_source = NULL;
+ p_channel->i_input_port = 0;
+ p_channel->i_input_vlan = 0;
+
+ /* Parse string */
+ i_field = 0;
+ for( psz_index = psz_str; (i_field != -1) && (*psz_index != '\0'); psz_index++ )
+ {
+ if( *psz_index == ';' )
+ {
+ /* Mark end of field */
+ *psz_index = '\0';
+
+ /* Parse field */
+ switch( i_field++ )
+ {
+ case 0: /* channel number */
+ p_channel->i_channel = strtol( psz_str, &psz_end, 0);
+ if( (*psz_str == '\0') || (*psz_end != '\0') )
+ {
+ i_field = -1;
+ }
+ break;
+ case 1: /* channel description */
+ i_field_length = strlen( psz_str );
+ if( i_field_length != 0 )
+ {
+ p_channel->psz_description = malloc( i_field_length + 1 );
+ if( p_channel->psz_description == NULL )
+ {
+ intf_ErrMsg("error: %s\n", strerror( ENOMEM ));
+ i_field = -1;
+ }
+ else
+ {
+ strcpy( p_channel->psz_description, psz_str );
+ }
+ }
+ break;
+ case 2: /* input method */
+ p_channel->i_input_method = strtol( psz_str, &psz_end, 0);
+ if( (*psz_str == '\0') || (*psz_end != '\0') )
+ {
+ i_field = -1;
+ }
+ break;
+ case 3: /* input source */
+ i_field_length = strlen( psz_str );
+ if( i_field_length != 0 )
+ {
+ p_channel->psz_input_source = malloc( i_field_length + 1 );
+ if( p_channel->psz_input_source == NULL )
+ {
+ intf_ErrMsg("error: %s\n", strerror( ENOMEM ));
+ i_field = -1;
+ }
+ else
+ {
+ strcpy( p_channel->psz_input_source, psz_str );
+ }
+ }
+ break;
+ case 4: /* input port */
+ p_channel->i_input_port = strtol( psz_str, &psz_end, 0);
+ if( (*psz_str == '\0') || (*psz_end != '\0') )
+ {
+ i_field = -1;
+ }
+ break;
+ case 5: /* input vlan */
+ p_channel->i_channel = strtol( psz_str, &psz_end, 0);
+ if( (*psz_str == '\0') || (*psz_end != '\0') )
+ {
+ i_field = -1;
+ }
+ break;
+ /* ... following fields are ignored */
+ }
+
+ /* Set new beginning of field */
+ psz_str = psz_index + 1;
+ }
+ }
+
+ /* At least the first three fields must be parsed sucessfully for function
+ * success. Other parsing errors are returned using i_field = -1. */
+ if( i_field < 3 )
+ {
+ /* Function fails. Free allocated strings */
+ if( p_channel->psz_description != NULL )
+ {
+ free( p_channel->psz_description );
+ }
+ if( p_channel->psz_input_source != NULL )
+ {
+ free( p_channel->psz_input_source );
+ }
+ return( 1 );
+ }
+
+ /* Return success */
+ return( 0 );
+}