5 kx
5 kx #ifdef HAVE_CONFIG_H
5 kx #include <config.h>
5 kx #endif
5 kx
5 kx #include <stdlib.h>
5 kx #include <stdio.h>
5 kx #include <sys/sysinfo.h>
5 kx #include <sys/types.h>
5 kx #include <stdint.h>
5 kx #include <dirent.h>
5 kx #include <sys/stat.h> /* chmod(2) */
5 kx #include <sys/file.h>
5 kx #include <sys/mman.h>
5 kx #include <fcntl.h>
5 kx #include <limits.h>
5 kx #include <string.h> /* strdup(3) */
5 kx #include <libgen.h> /* basename(3) */
5 kx #include <ctype.h> /* tolower(3) */
5 kx #include <errno.h>
5 kx #include <time.h>
5 kx #include <sys/time.h>
5 kx #include <pwd.h>
5 kx #include <grp.h>
5 kx #include <stdarg.h>
5 kx #include <unistd.h>
5 kx
5 kx #include <defs.h>
5 kx #include <cscm/bcf.h>
5 kx
5 kx #include <dlist.h>
5 kx #include <strbuf.h>
5 kx #include <repolist.h>
5 kx #include <wrapper.h>
5 kx
5 kx
5 kx #define RLIST_ERRMSG_SIZE 4096
5 kx
5 kx void rlist_error( const char *fmt, ... )
5 kx {
5 kx va_list arg_ptr;
5 kx char buf[RLIST_ERRMSG_SIZE];
5 kx char msg[RLIST_ERRMSG_SIZE];
5 kx char *format = "%s: %s\n";
5 kx
5 kx va_start( arg_ptr, fmt );
5 kx
5 kx vsnprintf( msg, RLIST_ERRMSG_SIZE, (const void *)fmt, arg_ptr );
5 kx
5 kx va_end( arg_ptr ); /* Reset variable arguments. */
5 kx
5 kx snprintf( buf, RLIST_ERRMSG_SIZE, format, "rlist", msg );
5 kx
5 kx (void)write( STDERR_FILENO, buf, strlen( buf ) );
5 kx
5 kx exit( 1 );
5 kx }
5 kx
5 kx rlist_errfunc rlist_fatal = rlist_error;
5 kx
5 kx
5 kx struct dlist *config = NULL;
5 kx
5 kx static void *bcf = NULL;
5 kx
5 kx static size_t read_bcf( void )
5 kx {
5 kx int fd;
5 kx struct stat st;
5 kx void *addr;
5 kx
5 kx fd = shm_open( CGIT_SHM_BCF, O_RDONLY, S_IRUSR | S_IWUSR );
5 kx if( fd == -1 )
5 kx {
5 kx rlist_fatal( "Canot open SHM/%s data", "cgit.bcf" );
5 kx return 0;
5 kx }
5 kx if( !fstat( fd, (struct stat *)&st ) )
5 kx {
5 kx addr = mmap( NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED, fd, 0 );
5 kx if( addr != MAP_FAILED )
5 kx {
5 kx bcf = malloc( (size_t)st.st_size );
5 kx if( !bcf )
5 kx {
5 kx (void)munmap( addr, (size_t)st.st_size );
5 kx rlist_fatal( "Canot allocate memory for SHM/%s data", "cgit.bcf" );
5 kx return 0;
5 kx }
5 kx memcpy( bcf, addr, (size_t)st.st_size );
5 kx (void)munmap( addr, (size_t)st.st_size );
5 kx return (size_t)st.st_size;
5 kx }
5 kx else
5 kx {
5 kx rlist_fatal( "Canot mmap SHM/%s data", "cgit.bcf" );
5 kx return 0;
5 kx }
5 kx }
5 kx else
5 kx {
5 kx rlist_fatal( "Canot stat SHM/%s data", "cgit.bcf" );
5 kx return 0;
5 kx }
5 kx }
5 kx
5 kx
5 kx static void check_bcf_ident( const void *bf, size_t size )
5 kx {
5 kx Bcf32_fhdr *fhdr = (Bcf32_fhdr *)bf;
5 kx
5 kx if( !fhdr )
5 kx rlist_fatal( "Invalid address of SHM/%s data", "cgit.bcf" );
5 kx
5 kx if( (size_t)fhdr->b_fsize != size )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid size", "cgit.bcf" );
5 kx if( memcmp( fhdr->b_ident, BCFMAG, (size_t)SZBCFMAG ) )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid MAGIC number", "cgit.bcf" );
5 kx if( fhdr->b_ident[BI_CLASS] != BCF_CLASS_32 )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid objects class", "cgit.bcf" );
5 kx #if __BYTE_ORDER == __LITTLE_ENDIAN
5 kx if( fhdr->b_ident[BI_DATA] != BCF_DATA_LSB )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid byte-order", "cgit.bcf" );
5 kx #else
5 kx if( fhdr->b_ident[BI_DATA] != BCF_DATA_MSB )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid byte-order", "cgit.bcf" );
5 kx #endif
5 kx if( fhdr->b_ident[BI_VERSION] != BV_CURRENT )
5 kx rlist_fatal( "Binary Config SHM/%s: invalid version", "cgit.bcf" );
5 kx }
5 kx
5 kx
5 kx /***************************************************************
5 kx Print config file functions:
5 kx */
5 kx static void __print_global_variable( void *data, void *user_data )
5 kx {
5 kx struct variable *variable = (struct variable *)data;
5 kx struct strbuf *sb = (struct strbuf *)user_data;
5 kx
5 kx if( !variable || !sb ) return;
5 kx
5 kx switch( variable->type )
5 kx {
5 kx case DT_NUMERICAL:
5 kx strbuf_addf( sb, " %s = %d;\n", variable->name, variable->_v.val );
5 kx break;
5 kx case DT_PATH:
5 kx strbuf_addf( sb, " %s = '%s';\n", variable->name, variable->_v.vptr );
5 kx break;
5 kx case DT_STRING:
5 kx strbuf_addf( sb, " %s = \"%s\";\n", variable->name, variable->_v.vptr );
5 kx break;
5 kx default:
5 kx break;
5 kx }
5 kx }
5 kx
5 kx static void print_global_variables( struct strbuf *sb, struct dlist *list )
5 kx {
5 kx if( list ) { dlist_foreach( list, __print_global_variable, (void *)sb ); }
5 kx }
5 kx
5 kx static void __print_repo_variable( void *data, void *user_data )
5 kx {
5 kx struct variable *variable = (struct variable *)data;
5 kx struct strbuf *sb = (struct strbuf *)user_data;
5 kx
5 kx if( !variable || !sb ) return;
5 kx
5 kx switch( variable->type )
5 kx {
5 kx case DT_NUMERICAL:
5 kx strbuf_addf( sb, " %s = %d;\n", variable->name, variable->_v.val );
5 kx break;
5 kx case DT_PATH:
5 kx strbuf_addf( sb, " %s = '%s';\n", variable->name, variable->_v.vptr );
5 kx break;
5 kx case DT_STRING:
5 kx strbuf_addf( sb, " %s = \"%s\";\n", variable->name, variable->_v.vptr );
5 kx break;
5 kx default:
5 kx break;
5 kx }
5 kx }
5 kx
5 kx static void print_repo_variables( struct strbuf *sb, struct dlist *list )
5 kx {
5 kx if( list ) { dlist_foreach( list, __print_repo_variable, (void *)sb ); }
5 kx }
5 kx
5 kx static void __print_repo( void *data, void *user_data )
5 kx {
5 kx struct repo *repo = (struct repo *)data;
5 kx struct strbuf *sb = (struct strbuf *)user_data;
5 kx
5 kx if( !repo || !sb ) return;
5 kx
5 kx strbuf_addf( sb, " repo '%s' {\n", repo->path );
5 kx if( repo->list )
5 kx {
5 kx print_repo_variables( sb, repo->list );
5 kx }
5 kx strbuf_addf( sb, " }\n\n" );
5 kx }
5 kx
5 kx static void print_repos( struct strbuf *sb, struct dlist *list )
5 kx {
5 kx if( list ) { dlist_foreach( list, __print_repo, (void *)sb ); }
5 kx }
5 kx
5 kx static void __print_section( void *data, void *user_data )
5 kx {
5 kx struct section *section = (struct section *)data;
5 kx struct strbuf *sb = (struct strbuf *)user_data;
5 kx
5 kx if( !section || !sb ) return;
5 kx
5 kx if( section->list )
5 kx {
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx strbuf_addf( sb, "section \"%s\" {\n\n", section->name );
5 kx print_repos( sb, section->list );
5 kx strbuf_addf( sb, "}\n\n" );
5 kx }
5 kx else if( section->type == ST_GLOBAL )
5 kx {
5 kx strbuf_addf( sb, "section \".global\" {\n" );
5 kx print_global_variables( sb, section->list );
5 kx strbuf_addf( sb, "}\n\n" );
5 kx }
5 kx }
5 kx }
5 kx
5 kx void print_config( struct strbuf *sb, struct dlist *list )
5 kx {
5 kx strbuf_addf( sb, "<pre><code class='language-C'>\n" );
5 kx strbuf_addf( sb, "/*******************************************************\n" );
5 kx strbuf_addf( sb, " Global variables are propagate into repo sections but\n" );
5 kx strbuf_addf( sb, " their values overrides by correspond repo variables.\n" );
5 kx strbuf_addf( sb, " */\n\n" );
5 kx if( list ) { dlist_foreach( list, __print_section, (void *)sb ); }
5 kx strbuf_addf( sb, "</code></pre>\n" );
5 kx }
5 kx /*
5 kx End of print config file functions.
5 kx ***************************************************************/
5 kx
5 kx
5 kx /**************************
5 kx lookup variable in repo:
5 kx */
5 kx static int __compare_variables_by_name( const void *a, const void *b )
5 kx {
5 kx struct variable *va = (struct variable *)a;
5 kx struct variable *vb = (struct variable *)b;
5 kx
5 kx if( !va || !vb ) return -1;
5 kx
5 kx return strcmp( (const char *)va->name, (const char *)vb->name );
5 kx }
5 kx
5 kx struct variable *lookup( struct repo *repo, struct variable *variable )
5 kx {
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !repo || !repo->list ) return NULL;
5 kx
5 kx found = dlist_find_data( repo->list, __compare_variables_by_name, (const void *)variable );
5 kx if( found )
5 kx return (struct variable *)(found->data);
5 kx return NULL;
5 kx }
5 kx
5 kx struct variable *lookup_global( struct section *section, struct variable *variable )
5 kx {
5 kx struct dlist *found = NULL;
5 kx
5 kx if( !section || !section->list ) return NULL;
5 kx
5 kx found = dlist_find_data( section->list, __compare_variables_by_name, (const void *)variable );
5 kx if( found )
5 kx return (struct variable *)(found->data);
5 kx return NULL;
5 kx }
5 kx
5 kx /**************
5 kx lookup repo:
5 kx */
5 kx struct repo *lookup_repo( struct dlist *config, const char *path )
5 kx {
5 kx struct dlist *list = NULL;
5 kx
5 kx if( !config || !path ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx struct repo *repo = (struct repo *)rlist->data;
5 kx if( !strcmp( (const char *)repo->path, path ) )
5 kx return repo;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /*****************
5 kx lookup section:
5 kx */
5 kx struct section *lookup_section( struct dlist *config, const char *name )
5 kx {
5 kx struct dlist *list = NULL;
5 kx
5 kx if( !config || !name ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section && section->type == ST_REPOS && !strcmp( (const char *)section->name, name ) )
5 kx return section;
5 kx
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /************************
5 kx lookup global section:
5 kx */
5 kx struct section *lookup_global_section( struct dlist *config )
5 kx {
5 kx struct dlist *list = NULL;
5 kx
5 kx if( !config ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section && section->type == ST_GLOBAL )
5 kx return section;
5 kx
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /******************
5 kx repolist length:
5 kx */
5 kx int repolist_length( struct dlist *config )
5 kx {
5 kx struct dlist *list = NULL;
5 kx int length = 0;
5 kx
5 kx if( !config ) return length;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx ++length;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return length;
5 kx }
5 kx
5 kx /***************
5 kx repolist nth:
5 kx */
5 kx struct repo *repolist_nth( struct dlist *config, int n )
5 kx {
5 kx struct dlist *list = NULL;
5 kx int length = 0;
5 kx
5 kx if( !config || n < 0 ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx if( length == n )
5 kx {
5 kx struct repo *repo = (struct repo *)rlist->data;
5 kx return repo;
5 kx }
5 kx ++length;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /**************************
5 kx repo position in config:
5 kx */
5 kx int repo_position( struct dlist *config, struct repo *repo )
5 kx {
5 kx struct dlist *list = NULL;
5 kx int position = -1;
5 kx
5 kx if( !config || !repo ) return position;
5 kx
5 kx position = 0;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx if( (struct repo *)rlist->data == repo )
5 kx {
5 kx return position;
5 kx }
5 kx ++position;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return -1;
5 kx }
5 kx
5 kx
5 kx /**************************************
5 kx parent section node of repolist nth:
5 kx */
5 kx struct dlist *parent_section_node_repolist_nth( struct dlist *config, int n )
5 kx {
5 kx struct dlist *list = NULL;
5 kx int length = 0;
5 kx
5 kx if( !config || n < 0 ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx if( length == n )
5 kx {
5 kx return list;
5 kx }
5 kx ++length;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx /************************************
5 kx parent rlist node of repolist nth:
5 kx */
5 kx struct dlist *parent_rlist_node_repolist_nth( struct dlist *config, int n )
5 kx {
5 kx struct dlist *list = NULL;
5 kx int length = 0;
5 kx
5 kx if( !config || n < 0 ) return NULL;
5 kx
5 kx list = config;
5 kx while( list )
5 kx {
5 kx struct section *section = (struct section *)list->data;
5 kx
5 kx if( section->type == ST_REPOS )
5 kx {
5 kx struct dlist *rlist = section->list;
5 kx while( rlist )
5 kx {
5 kx if( length == n )
5 kx {
5 kx return rlist;
5 kx }
5 kx ++length;
5 kx rlist = dlist_next( rlist );
5 kx }
5 kx }
5 kx list = dlist_next( list );
5 kx }
5 kx
5 kx return NULL;
5 kx }
5 kx
5 kx
5 kx
5 kx /**********************************************
5 kx Provide all global variables into each repo
5 kx if that variable is not present in the repo:
5 kx */
5 kx static void __provide_foreach_data( void *data, void *user_data )
5 kx {
5 kx struct variable *variable = (struct variable *)data;
5 kx struct repo *repo = (struct repo *)user_data;
5 kx
5 kx if( !repo || !variable ) return;
5 kx
5 kx if( !lookup( repo, variable ) )
5 kx {
5 kx struct variable *var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx memcpy( (void *)var, (void *)variable, sizeof(struct variable) );
5 kx repo->list = dlist_append( repo->list, (void *)var );
5 kx }
5 kx }
5 kx
5 kx static void __provide_foreach_repos( void *data, void *user_data )
5 kx {
5 kx struct section *global = (struct section *)user_data;
5 kx
5 kx if( !global || !global->list ) return;
5 kx
5 kx dlist_foreach( global->list, __provide_foreach_data, data );
5 kx }
5 kx
5 kx static void __provide_foreach_sections( void *data, void *user_data )
5 kx {
5 kx struct section *section = (struct section *)data;
5 kx if( !section || section->type == ST_GLOBAL || !section->list ) return;
5 kx
5 kx dlist_foreach( section->list, __provide_foreach_repos, user_data );
5 kx }
5 kx
5 kx static void provide_global_data( struct dlist *tree, struct section *global )
5 kx {
5 kx if( tree ) { dlist_foreach( tree, __provide_foreach_sections, (void *)global ); }
5 kx }
5 kx /*
5 kx **********************************************/
5 kx
5 kx /**********************************************
5 kx Free REPO list functions:
5 kx */
5 kx static void __free_variable( void *data, void *user_data )
5 kx {
5 kx struct variable *variable = (struct variable *)data;
5 kx if( variable ) free( variable );
5 kx }
5 kx
5 kx static void free_variables( struct dlist *list )
5 kx {
5 kx if( list ) { dlist_free( list, __free_variable ); }
5 kx }
5 kx
5 kx static void __free_repo( void *data, void *user_data )
5 kx {
5 kx struct repo *repo = (struct repo *)data;
5 kx if( !repo ) return;
5 kx if( repo->list ) { free_variables( repo->list ); }
5 kx free( repo );
5 kx }
5 kx
5 kx static void free_repos( struct dlist *list )
5 kx {
5 kx if( list ) { dlist_free( list, __free_repo ); }
5 kx }
5 kx
5 kx static void __free_section( void *data, void *user_data )
5 kx {
5 kx struct section *section = (struct section *)data;
5 kx if( !section ) return;
5 kx
5 kx if( section->list )
5 kx {
5 kx if( section->type == ST_GLOBAL )
5 kx free_variables( section->list );
5 kx else if( section->type == ST_REPOS )
5 kx free_repos( section->list );
5 kx }
5 kx free( section );
5 kx }
5 kx
5 kx static void free_repolist( struct dlist *list )
5 kx {
5 kx if( list ) { dlist_free( list, __free_section ); }
5 kx }
5 kx /*
5 kx **********************************************/
5 kx
5 kx void free_config( void )
5 kx {
5 kx free_repolist( config ); config = NULL;
5 kx if( bcf ) { free( bcf ); bcf = NULL; }
5 kx }
5 kx
5 kx static struct dlist *read_repolist( const void *bf )
5 kx {
5 kx struct dlist *tree = NULL;
5 kx Bcf32_fhdr *fhdr = NULL;
5 kx unsigned char *ftab, *stab;
5 kx
5 kx ftab = (unsigned char *)bf;
5 kx fhdr = (Bcf32_fhdr *)ftab;
5 kx
5 kx if( !fhdr )
5 kx return tree;
5 kx
5 kx stab = (unsigned char *)(ftab + (int)fhdr->b_stoff);
5 kx
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "BCF: header's size in bytes: %d\n", fhdr->b_hsize );
5 kx fprintf( stderr, "BCF: Whole BCF file size in bytes: %d\n", fhdr->b_fsize );
5 kx fprintf( stderr, "BCF: section header table’s file offset in bytes: %d\n", fhdr->b_shoff );
5 kx fprintf( stderr, "BCF: section header's size in bytes: %d\n", fhdr->b_shentsize );
5 kx fprintf( stderr, "BCF: number of entries in section headers table: %d\n", fhdr->b_shnum );
5 kx fprintf( stderr, "BCF: repository header table’s file offset in bytes: %d\n", fhdr->b_rhoff );
5 kx fprintf( stderr, "BCF: repository header's size in bytes: %d\n", fhdr->b_rhentsize );
5 kx fprintf( stderr, "BCF: number of entries in repository headers table: %d\n", fhdr->b_rhnum );
5 kx fprintf( stderr, "BCF: data entries table’s file offset in bytes: %d\n", fhdr->b_dtoff );
5 kx fprintf( stderr, "BCF: data entry's size in bytes: %d\n", fhdr->b_dtentsize );
5 kx fprintf( stderr, "BCF: number of entries in data entries table: %d\n", fhdr->b_dtnum );
5 kx fprintf( stderr, "BCF: string table’s file offset in bytes: %d\n\n", fhdr->b_stoff );
5 kx #endif
5 kx
5 kx {
5 kx Bcf32_shdr *shdr = NULL;
5 kx int s = 0;
5 kx
5 kx struct section *global = NULL;
5 kx
5 kx shdr = (Bcf32_shdr *)((unsigned char *)bf + (int)fhdr->b_shoff);
5 kx
5 kx while( s < fhdr->b_shnum )
5 kx {
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "SECTION: s_name: %s\n", shdr->s_name );
5 kx fprintf( stderr, "SECTION: s_type: %d\n", shdr->s_type );
5 kx fprintf( stderr, "SECTION: s_shdr (offset in string table): %d\n", shdr->s_shdr );
5 kx fprintf( stderr, "SECTION: s_sdata (file offset to data): %d\n", shdr->s_sdata );
5 kx fprintf( stderr, "SECTION: s_dnum (number of data entries): %d\n", shdr->s_dnum );
5 kx fprintf( stderr, "SECTION: name: \"%s\"\n\n", stab + (int)shdr->s_shdr );
5 kx #endif
5 kx
5 kx if( shdr->s_type == ST_GLOBAL )
5 kx {
5 kx Bcf32_dntr *dntr = NULL;
5 kx int d = 0;
5 kx
5 kx struct section *sec = NULL;
5 kx sec = (struct section *)xmalloc( sizeof(struct section) );
5 kx sec->type = ST_GLOBAL;
5 kx sec->name = (unsigned char *)(stab + (int)shdr->s_shdr); /*do not allocate, all in bcf */
5 kx tree = dlist_append( tree, (void *)sec );
5 kx global = sec;
5 kx
5 kx dntr = (Bcf32_dntr *)(ftab + (int)shdr->s_sdata);
5 kx
5 kx while( d < shdr->s_dnum )
5 kx {
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "DATA: d_name: %s\n", stab + (int)dntr->d_name );
5 kx #endif
5 kx
5 kx switch( dntr->d_type )
5 kx {
5 kx case DT_NUMERICAL:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "DATA: _v.d_value: %d\n\n", dntr->_v.d_value );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_NUMERICAL;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.val = (int)dntr->_v.d_value;
5 kx sec->list = dlist_append( sec->list, (void *)var );
5 kx }
5 kx break;
5 kx case DT_PATH:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "DATA: _v.d_valptr (path): '%s';\n\n", stab + (int)dntr->_v.d_valptr );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_PATH;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.vptr = (unsigned char *)(stab + (int)dntr->_v.d_valptr);
5 kx sec->list = dlist_append( sec->list, (void *)var );
5 kx }
5 kx break;
5 kx case DT_STRING:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "DATA: _v.d_valptr (string): \"%s\";\n\n", stab + (int)dntr->_v.d_valptr );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_STRING;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.vptr = (unsigned char *)(stab + (int)dntr->_v.d_valptr);
5 kx sec->list = dlist_append( sec->list, (void *)var );
5 kx }
5 kx break;
5 kx default:
5 kx break;
5 kx }
5 kx
5 kx ++d;
5 kx ++dntr;
5 kx
5 kx } /* End of while( global data ) */
5 kx
5 kx }
5 kx else if( shdr->s_type == ST_REPOS )
5 kx {
5 kx Bcf32_rhdr *rhdr = NULL;
5 kx int r = 0;
5 kx
5 kx struct section *sec = NULL;
5 kx sec = (struct section *)xmalloc( sizeof(struct section) );
5 kx sec->type = ST_REPOS;
5 kx sec->name = (unsigned char *)(stab + (int)shdr->s_shdr); /*do not allocate, all in bcf */
5 kx tree = dlist_append( tree, (void *)sec );
5 kx
5 kx rhdr = (Bcf32_rhdr *)(ftab + (int)shdr->s_sdata);
5 kx
5 kx while( r < shdr->s_dnum )
5 kx {
5 kx int d = 0;
5 kx Bcf32_dntr *dntr = NULL;
5 kx
5 kx struct repo *repo = NULL;
5 kx repo = (struct repo *)xmalloc( sizeof(struct repo) );
5 kx repo->path = (unsigned char *)(stab + (int)rhdr->r_rhdr); /*do not allocate, all in bcf */
5 kx sec->list = dlist_append( sec->list, (void *)repo );
5 kx
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "REPO: path: %s\n", stab + (int)rhdr->r_rhdr );
5 kx #endif
5 kx dntr = (Bcf32_dntr *)(ftab + (int)rhdr->r_rdata);
5 kx
5 kx while( d < rhdr->r_dnum )
5 kx {
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "REPO's DATA: d_name: %s\n", stab + (int)dntr->d_name );
5 kx #endif
5 kx switch( dntr->d_type )
5 kx {
5 kx case DT_NUMERICAL:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "REPO's DATA: _v.d_value: %d\n\n", dntr->_v.d_value );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_NUMERICAL;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.val = (int)dntr->_v.d_value;
5 kx repo->list = dlist_append( repo->list, (void *)var );
5 kx }
5 kx break;
5 kx case DT_PATH:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "REPO's DATA: _v.d_valptr (path): '%s';\n\n", stab + (int)dntr->_v.d_valptr );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_PATH;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.vptr = (unsigned char *)(stab + (int)dntr->_v.d_valptr);
5 kx repo->list = dlist_append( repo->list, (void *)var );
5 kx }
5 kx break;
5 kx case DT_STRING:
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "REPO's DATA: _v.d_valptr (string): \"%s\";\n\n", stab + (int)dntr->_v.d_valptr );
5 kx #endif
5 kx {
5 kx struct variable *var = NULL;
5 kx var = (struct variable *)xmalloc( sizeof(struct variable) );
5 kx var->type = DT_STRING;
5 kx var->name = (unsigned char *)(stab + (int)dntr->d_name); /*do not allocate, all in bcf */
5 kx var->_v.vptr = (unsigned char *)(stab + (int)dntr->_v.d_valptr);
5 kx repo->list = dlist_append( repo->list, (void *)var );
5 kx }
5 kx break;
5 kx default:
5 kx break;
5 kx }
5 kx
5 kx ++d;
5 kx ++dntr;
5 kx
5 kx } /* End of while( repo data ) */
5 kx
5 kx ++r;
5 kx ++rhdr;
5 kx
5 kx } /* End of while( repos ) */
5 kx
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "\n" );
5 kx #endif
5 kx }
5 kx else
5 kx {
5 kx rlist_fatal( "Invalid section in the SHM/%s data", "cgit.bcf" );
5 kx #if __DEBUG__ == 1
5 kx fprintf( stderr, "SECTION: empty\n" );
5 kx #endif
5 kx }
5 kx
5 kx ++s;
5 kx ++shdr;
5 kx
5 kx } /* End of while( sections ) */
5 kx
5 kx if( global )
5 kx provide_global_data( tree, global );
5 kx }
5 kx
5 kx return tree;
5 kx }
5 kx
5 kx
5 kx struct dlist *read_config( void )
5 kx {
5 kx size_t bsize = 0;
5 kx
5 kx if( (bsize = read_bcf()) )
5 kx {
5 kx check_bcf_ident( bcf, bsize ); /* fatal on error */
5 kx return read_repolist( bcf );
5 kx }
5 kx
5 kx return NULL;
5 kx }