⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp-conf.c

📁 this is sample about DHCP-agent
💻 C
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-conf.c,v 1.12 2003/07/13 04:52:48 actmodern Exp $ *  * Copyright 2002 Thamer Alharbash <tmh@whitefang.com> *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. *  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Configuration file parser. * * Our parsing is more complicated than what the varfile does. * Here we accept an array of structures which tell us what to * expect.  We build directive lists from these structures and * pass them up. *  */#define MODULE_NAME "dhcp-conf.c"#include "dhcp-local.h"#include "dhcp-libutil.h"#include "dhcp-tokenizer.h"#include "dhcp-conf.h"/* forward declaration of argument drivers. */static void *compile_arg_identifier(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_ip_address(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_hw_address(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_assignment(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_boolean(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_string(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_string_list(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);static void *compile_arg_group(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols);/* forward declaration of argument destroyers *//* we only need these two. */static void destroy_arg_string_list(void *data);static void destroy_arg_group(void *data);/* argument_compiler_dispatch table -- these are indexed by the types in dhcp-conf.h */argument_compiler_t argument_compilers[] = {    compile_arg_identifier,    compile_arg_ip_address,    compile_arg_hw_address,    compile_arg_assignment,    compile_arg_boolean,    compile_arg_string,    compile_arg_string_list,    compile_arg_group,};/* argument destroyer dispatch table -- these are indexed by the types in dhcp-conf.h */argument_destroy_t argument_destroyers[] = {    xfree,    xfree,    xfree,    xfree,    xfree,    xfree,    destroy_arg_string_list,    destroy_arg_group,};/* * * * * * * * * * * * * * * * constructors/destructors  * * * * * * * * * * * * * * * */static directive_t *directive_create(void){    directive_t *directive;    directive = xcalloc(sizeof(directive_t));    directive->argument_types = list_create();    directive->arguments = list_create();    return directive;}static arg_type_t *arg_type_create(arg_type_t arg){    arg_type_t *arg_type = xmalloc(sizeof(arg_type_t));    *arg_type = arg;    return arg_type;}static void arg_type_destroy(arg_type_t *arg){    xfree(arg);    return;}static void directive_destroy(directive_t *directive){    list_t *arg_ptr;    list_t *type_ptr;    arg_type_t *arg_type;    void       *arg_data;    arg_ptr = directive->arguments;    type_ptr = directive->argument_types;    /* iterate through the list of arguments.     * and call the destroy routine per argument. */    list_rewind(type_ptr);    list_rewind(arg_ptr);    while((arg_type = list_next(type_ptr)) != NULL) {        /* each arg_type tells us which destructor to call on the         * argument data. */        arg_data = list_next(arg_ptr);        /* we're automatically rewound after any removal. */        /* this won't free up the datums themselves. */        list_remove_by_datum(type_ptr, arg_type);         list_remove_by_datum(arg_ptr,  arg_data);        /* now destroy ourselves. */        argument_destroyers[*arg_type](arg_data);        arg_type_destroy((arg_type_t *)arg_type);    }    list_destroy(type_ptr, NULL);    list_destroy(arg_ptr, NULL);    return;}static void directive_destroy_l(void *p){    directive_destroy(p);}conf_t *conf_create(const command_t **commands, const char *filename){    conf_t *conf;    conf = xmalloc(sizeof(conf_t));    conf->tokenizer = tokenizer_create(filename);    if(conf->tokenizer == NULL) {        ERROR_MESSAGE("could not open configuration file: %s", filename);        xfree(conf);        return NULL;    }    conf->filename = xstrdup(filename);    conf->commands = commands;    conf->directives = list_create();    return conf;}void conf_destroy(conf_t *conf){    xfree(conf->filename);    tokenizer_destroy(conf->tokenizer);    list_destroy(conf->directives, directive_destroy_l);    xfree(conf);    return;}/* * * * * * * * * * * * * argument compilers  * * * * * * * * * * * * */static void *compile_arg_identifier(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    arg_symbol_t *identifier_symbol = NULL;    const char *string;    token_t token;    const char **ptr;    int i;    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    /* identifiers are strings. so check for that type and do     * a comparison against our data. */    if(token != TOKEN_STRING)        return NULL;    string = tokenizer_get_data(conf->tokenizer);    i = 0;    for(ptr = argument_strings; *ptr != NULL; ptr++) {        if(!strcmp(string, *ptr)) {            identifier_symbol = xmalloc(sizeof(arg_symbol_t));            *identifier_symbol = argument_symbols[i];            break;        }        i++;    }    if(identifier_symbol == NULL)        ERROR_MESSAGE("unknown identifier: %s\n", string);    return identifier_symbol;}static void *compile_arg_ip_address(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    ip_addr_t *ip_addr = NULL;    const char *string;    token_t token;    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_STRING)        return NULL;    string = tokenizer_get_data(conf->tokenizer);    ip_addr = string_ip_to_ip_addr(string);    return ip_addr;}static void *compile_arg_hw_address(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    eth_addr_t *eth_addr = NULL;    const char *string;    token_t token;    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_STRING)        return NULL;    string = tokenizer_get_data(conf->tokenizer);    eth_addr = string_eth_addr_to_eth_addr(string);    return eth_addr;}static void *compile_arg_assignment(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    uint8_t *placeholder;    token_t token;    /* this is fairly easy check if the atom is an assignment and just return an empty placeholder.     * we really don't care what kind of assignment it is since we only have one. in the future     * we may create more. */    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_ASSIGNMENT)        return NULL;    placeholder = xmalloc(sizeof(uint8_t));    *placeholder = 1;    return placeholder;}static void *compile_arg_boolean(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    uint8_t *bool_val;    token_t token;    const char *string;    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_STRING)        return NULL;    string = tokenizer_get_data(conf->tokenizer);    if(!strcmp(string, "yes")) {        bool_val = xmalloc(sizeof(uint8_t));        *bool_val = 1;    } else if(!strcmp(string, "no")) {        bool_val = xmalloc(sizeof(uint8_t));        *bool_val = 0;    } else {        ERROR_MESSAGE("%s is not a boolean value as expected. legal boolean values are \"yes\" and \"no\"");        bool_val = NULL;    }    return bool_val;}static void *compile_arg_string(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    char *string_arg;    const char *string;    token_t token;    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);        if(token != TOKEN_STRING)        return NULL;    string = tokenizer_get_data(conf->tokenizer);    string_arg = xstrdup(string);    return string_arg;}static void *compile_arg_string_list(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    list_t *string_list;    char *string;    token_t token;    string_list = list_create();    /* ask compile_arg_string_list to do the work for us.      * we peek for commas but that's about it. */    while(1)  {        /* next one should be string or it's a parser error. */        string = compile_arg_string(conf, argument_strings, argument_symbols);        if(string == NULL) {            ERROR_MESSAGE("no string list found at %d\n", conf_get_line_no(conf));            list_destroy(string_list, xfree);            return NULL;        }        list_add_to_end(string_list, string);        /* now peek for a comma, if available keep going. */        token = tokenizer_peek_next_token_ignore_newlines(conf->tokenizer);        if(token == TOKEN_COMMA) {            token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);        } else {            break;        }    }     return string_list;}/* compile the command. follow the command argument types and store them. */static directive_t *compile_command(conf_t *conf, const command_t *command){    directive_t *directive;    void *args;    token_t token;    int i;    arg_type_t *arg_type;    /* create a new directive. */    directive = directive_create();    /* set the command code. */    directive->command_code = command->command_code;    for(i = 0;i < command->argument_len; i++) {        /* now try to compile the arguments based on the type. */        args = argument_compilers[command->argument_types[i]](conf, command->argument_strings[i],                                                              command->argument_symbols[i]);        if(args == NULL) {            ERROR_MESSAGE("unable to compile directive at line %d\n", conf_get_line_no(conf));            directive_destroy(directive);            return NULL;        }        arg_type = arg_type_create(command->argument_types[i]);        list_add_to_end(directive->argument_types, arg_type);        list_add_to_end(directive->arguments, args);    }    /* we're done. now we need a semicolon to end this directive. */    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_SEMICOLON) {        ERROR_MESSAGE("semi colon terminator not present where expected at line: %d\n", conf_get_line_no(conf));        directive_destroy(directive);        return NULL;    }    return directive;}static directive_t *compile_directive(conf_t *conf){    const char *token_string;    directive_t *directive;    const command_t *command;    int i;    /* we expect the string is already read from the parser     * before we're called. */    token_string = tokenizer_get_data(conf->tokenizer);    /* now do a comparison and find our command_t. */    for(i = 0;;i++)  {        command = conf->commands[i];         if(command == NULL)            break;        if(!strcmp(command->command_name, token_string)) {            /* we have a match. try to parse the rest so we have a new command_t filled out. */            directive = compile_command(conf, command);            if(command == NULL)                break;            return directive;        }    }    /* we didn't match a command name. */    return NULL;}/* a group is just a grouping of additional commands. we create a directive list and pass it up.*/static void *compile_arg_group(conf_t *conf, const char **argument_strings, const arg_symbol_t *argument_symbols){    token_t token;    directive_t *directive;    list_t *directive_list;    directive_list = list_create();    /* if we have a brace, go ahead and read in a command list. by compiling each command under it     * as per the commands allowed in the group. */    token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);    if(token != TOKEN_BLOCK_OPEN)        return NULL;         /* FIXME: currently empty groups are going to return the same error as a missing brace. */    while(1) {        token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);        if(token == TOKEN_BLOCK_CLOSE)            return directive_list;        /* we should always start with a string. */        if(token != TOKEN_STRING)            goto error;        directive = compile_directive(conf);        if(directive == NULL)             goto error;        list_add_to_end(directive_list, directive);            } error:        list_destroy(directive_list, directive_destroy_l);        return NULL;}/* * * * * * * * * * * * * * * * * * argument destruction routines * * * * * * * * * * * * * * * * * *//* most are just freed with xfree. these two are special because * they contain lists. */static void destroy_arg_string_list(void *data){    list_t *list = data;    list_destroy(list, xfree); /* just free up a list of strings. */}static void destroy_arg_group(void *data){    list_t *list = data;    list_destroy(list, directive_destroy_l); /* free up a list of directives. */    return;}/* compile the file into a list of directives. */int conf_compile_directives(conf_t *conf){    token_t token;    directive_t *directive;    while(1) {        token = tokenizer_get_next_token_ignore_newlines(conf->tokenizer);        if(token == TOKEN_EOF) /* end of file */            return CONF_OK;        /* we should always start with a string. */        if(token != TOKEN_STRING)            return CONF_ERROR;        directive = compile_directive(conf);        if(directive == NULL)            return CONF_ERROR; /* if we got a string it should match or error. */        list_add_to_end(conf->directives, directive);    }    /* we should never get here. */    FATAL_MESSAGE("i don't know why i'm here. this is a bug. report me.");    exit(1); /* do away with compiler warning. */}list_t *conf_get_directives(conf_t *conf){    return conf->directives;}int conf_get_line_no(conf_t *conf){    return tokenizer_get_line_no(conf->tokenizer);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -