data_list.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:12k
- /*
- * netsnmp_data_list.c
- *
- * $Id: data_list.c,v 5.7 2004/06/28 12:20:23 rstory Exp $
- */
- #include <net-snmp/net-snmp-config.h>
- #include <net-snmp/net-snmp-includes.h>
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- /*
- * prototypes
- */
- NETSNMP_INLINE void
- netsnmp_data_list_add_node(netsnmp_data_list **head, netsnmp_data_list *node);
- /** @defgroup data_list generic linked-list data handling with a string as a key.
- * @ingroup library
- * @{
- */
- /** frees the data and a name at a given data_list node.
- * Note that this doesn't free the node itself.
- * @param node the node for which the data should be freed
- */
- NETSNMP_INLINE void
- netsnmp_free_list_data(netsnmp_data_list *node)
- {
- Netsnmp_Free_List_Data *beer;
- if (!node)
- return;
- beer = node->free_func;
- if (beer)
- (beer) (node->data);
- SNMP_FREE(node->name);
- }
- /** frees all data and nodes in a list.
- * @param head the top node of the list to be freed.
- */
- NETSNMP_INLINE void
- netsnmp_free_all_list_data(netsnmp_data_list *head)
- {
- netsnmp_data_list *tmpptr;
- for (; head;) {
- netsnmp_free_list_data(head);
- tmpptr = head;
- head = head->next;
- SNMP_FREE(tmpptr);
- }
- }
- /** adds creates a data_list node given a name, data and a free function ptr.
- * @param name the name of the node to cache the data.
- * @param data the data to be stored under that name
- * @param beer A function that can free the data pointer (in the future)
- * @return a newly created data_list node which can be given to the netsnmp_add_list_data function.
- */
- NETSNMP_INLINE netsnmp_data_list *
- netsnmp_create_data_list(const char *name, void *data,
- Netsnmp_Free_List_Data * beer)
- {
- netsnmp_data_list *node = SNMP_MALLOC_TYPEDEF(netsnmp_data_list);
- if (!node)
- return NULL;
- node->name = strdup(name);
- node->data = data;
- node->free_func = beer;
- return node;
- }
- /** adds data to a datalist
- * @note netsnmp_data_list_add_node is preferred
- * @param head a pointer to the head node of a data_list
- * @param node a node to stash in the data_list
- */
- /** */
- NETSNMP_INLINE void
- netsnmp_add_list_data(netsnmp_data_list **head, netsnmp_data_list *node)
- {
- netsnmp_data_list_add_node(head, node);
- }
- /** adds data to a datalist
- * @param head a pointer to the head node of a data_list
- * @param node a node to stash in the data_list
- */
- NETSNMP_INLINE void
- netsnmp_data_list_add_node(netsnmp_data_list **head, netsnmp_data_list *node)
- {
- netsnmp_data_list *ptr;
- netsnmp_assert(NULL != head);
- netsnmp_assert(NULL != node);
- netsnmp_assert(NULL != node->name);
- if (!*head) {
- *head = node;
- return;
- }
- DEBUGMSGTL(("data_list","adding key '%s'n", node->name));
- if (0 == strcmp(node->name, (*head)->name)) {
- netsnmp_assert("list key" == "is unique"); /* always fail */
- snmp_log(LOG_WARNING,
- "WARNING: adding duplicate key '%s' to data listn",
- node->name);
- }
- for (ptr = *head; ptr->next != NULL; ptr = ptr->next) {
- netsnmp_assert(NULL != ptr->name);
- if (0 == strcmp(node->name, ptr->name)) {
- netsnmp_assert("list key" == "is unique"); /* always fail */
- snmp_log(LOG_WARNING,
- "WARNING: adding duplicate key '%s' to data listn",
- node->name);
- }
- }
- netsnmp_assert(NULL != ptr);
- if (ptr) /* should always be true */
- ptr->next = node;
- }
- /** adds data to a datalist
- * @param head a pointer to the head node of a data_list
- * @param name the name of the node to cache the data.
- * @param data the data to be stored under that name
- * @param beer A function that can free the data pointer (in the future)
- * @return a newly created data_list node which was inserted in the list
- */
- NETSNMP_INLINE netsnmp_data_list *
- netsnmp_data_list_add_data(netsnmp_data_list **head, const char *name,
- void *data, Netsnmp_Free_List_Data * beer)
- {
- netsnmp_data_list *node = netsnmp_create_data_list(name, data, beer);
- if(NULL == node) {
- snmp_log(LOG_ERR,"could not allocate memory for node.");
- return NULL;
- }
-
- netsnmp_add_list_data(head, node);
- return node;
- }
- /** returns a data_list node's data for a given name within a data_list
- * @param head the head node of a data_list
- * @param name the name to find
- * @return a pointer to the data cached at that node
- */
- NETSNMP_INLINE void *
- netsnmp_get_list_data(netsnmp_data_list *head, const char *name)
- {
- for (; head; head = head->next)
- if (head->name && strcmp(head->name, name) == 0)
- break;
- if (head)
- return head->data;
- return NULL;
- }
- /** returns a data_list node for a given name within a data_list
- * @param head the head node of a data_list
- * @param name the name to find
- * @return a pointer to the data_list node
- */
- NETSNMP_INLINE netsnmp_data_list *
- netsnmp_get_list_node(netsnmp_data_list *head, const char *name)
- {
- for (; head; head = head->next)
- if (head->name && strcmp(head->name, name) == 0)
- break;
- if (head)
- return head;
- return NULL;
- }
- /** Removes a named node from a data_list (and frees it)
- * @param realhead a pointer to the head node of a data_list
- * @param name the name to find and remove
- * @return 0 on successful find-and-delete, 1 otherwise.
- */
- int
- netsnmp_remove_list_node(netsnmp_data_list **realhead, const char *name)
- {
- netsnmp_data_list *head, *prev;
- for (head = *realhead, prev = NULL; head;
- prev = head, head = head->next) {
- if (head->name && strcmp(head->name, name) == 0) {
- if (prev)
- prev->next = head->next;
- else
- *realhead = head->next;
- netsnmp_free_list_data(head);
- free(head);
- return 0;
- }
- }
- return 1;
- }
- /** used to store registered save/parse handlers (specifically, parsing info) */
- static netsnmp_data_list *saveHead;
- /** registers to store a data_list set of data at persistant storage time
- *
- * @param datalist the data to be saved
- * @param type the name of the application to save the data as. If left NULL the default application name that was registered during the init_snmp call will be used (recommended).
- * @param token the unique token identifier string to use as the first word in the persistent file line.
- * @param data_list_save_ptr a function pointer which will be called to save the rest of the data to a buffer.
- * @param data_list_read_ptr a function pointer which can read the remainder of a saved line and return the application specific void * pointer.
- * @param data_list_free_ptr a function pointer which will be passed to the data node for freeing it in the future when/if the list/node is cleaned up or destroyed.
- */
- void
- netsnmp_register_save_list(netsnmp_data_list **datalist,
- const char *type, const char *token,
- Netsnmp_Save_List_Data *data_list_save_ptr,
- Netsnmp_Read_List_Data *data_list_read_ptr,
- Netsnmp_Free_List_Data *data_list_free_ptr) {
- netsnmp_data_list_saveinfo *info =
- SNMP_MALLOC_TYPEDEF(netsnmp_data_list_saveinfo);
- if (!info) {
- snmp_log(LOG_ERR, "couldn't malloc a netsnmp_data_list_saveinfo typedef");
- return;
- }
- info->datalist = datalist;
- info->token = token;
- info->type = type;
- if (!info->type) {
- info->type = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
- NETSNMP_DS_LIB_APPTYPE);
- }
- /* function which will save the data */
- info->data_list_save_ptr = data_list_save_ptr;
- if (data_list_save_ptr)
- snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
- netsnmp_save_all_data_callback, info);
- /* function which will read the data back in */
- info->data_list_read_ptr = data_list_read_ptr;
- if (data_list_read_ptr) {
- /** @todo netsnmp_register_save_list should handle the same token name being saved from different types? */
- netsnmp_add_list_data(&saveHead,
- netsnmp_create_data_list(token, info, NULL));
- register_config_handler(type, token, netsnmp_read_data_callback,
- NULL /* XXX */, NULL);
- }
- info->data_list_free_ptr = data_list_free_ptr;
- }
- /** intended to be registerd as a callback operation.
- * It should be registered using:
- *
- * snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA, netsnmp_save_all_data_callback, INFO_POINTER);
- *
- * where INFO_POINTER is a pointer to a netsnmp_data_list_saveinfo object containing apporpriate registration information
- */
- int
- netsnmp_save_all_data_callback(int major, int minor,
- void *serverarg, void *clientarg) {
- netsnmp_data_list_saveinfo *info = clientarg;
- if (!clientarg) {
- snmp_log(LOG_WARNING, "netsnmp_save_all_data_callback called with no passed data");
- return SNMP_ERR_NOERROR;
- }
- netsnmp_save_all_data(*(info->datalist), info->type, info->token,
- info->data_list_save_ptr);
- return SNMP_ERR_NOERROR;
- }
- /** intended to be called as a callback during persistent save operations.
- * See the netsnmp_save_all_data_callback for where this is typically used. */
- int
- netsnmp_save_all_data(netsnmp_data_list *head,
- const char *type, const char *token,
- Netsnmp_Save_List_Data * data_list_save_ptr)
- {
- char buf[SNMP_MAXBUF], *cp;
- for (; head; head = head->next) {
- if (head->name) {
- /* save begining of line */
- snprintf(buf, sizeof(buf), "%s ", token);
- cp = buf + strlen(buf);
- cp = read_config_save_octet_string(cp, (u_char*)head->name,
- strlen(head->name));
- *cp++ = ' ';
- /* call registered function to save the rest */
- if (!(data_list_save_ptr)(cp,
- sizeof(buf) - strlen(buf),
- head->data)) {
- read_config_store(type, buf);
- }
- }
- }
- return SNMP_ERR_NOERROR;
- }
- /** @todo make netsnmp_read_data_callback deal with a free routine */
- /** intended to be registerd as a .conf parser
- * It should be registered using:
- *
- * register_app_config_handler("token", netsnmp_read_data_callback, XXX)
- *
- * where INFO_POINTER is a pointer to a netsnmp_data_list_saveinfo object containing apporpriate registration information
- */
- void
- netsnmp_read_data_callback(const char *token, char *line) {
- netsnmp_data_list_saveinfo *info;
- char *dataname = NULL;
- size_t dataname_len;
- void *data = NULL;
- /* find the stashed information about what we're parsing */
- info = netsnmp_get_list_data(saveHead, token);
- if (!info) {
- snmp_log(LOG_WARNING, "netsnmp_read_data_callback called without previously registered subparser");
- return;
- }
- /* read in the token */
- line =
- read_config_read_data(ASN_OCTET_STR, line,
- &dataname, &dataname_len);
- if (!line || !dataname)
- return;
- /* call the sub-parser to read the rest */
- data = (info->data_list_read_ptr)(line, strlen(line));
- if (!data) {
- free(dataname);
- return;
- }
- /* add to the datalist */
- netsnmp_add_list_data(info->datalist,
- netsnmp_create_data_list(dataname, data,
- info->data_list_free_ptr));
- return;
- }