# mib2c.storage.conf:
#
#  This is a special mib2c.conf file that assumes that you want to do
#  all storage of information locally rather than pulling the
#  information from another source outside the agent (EG, the
#  kernel).  To accomplish this, it defines a structure for the
#  storage of tables and assumes you want to use the header_complex
#  functions for retrieving and storing that data in a local data
#  store.  It even writes a .conf file parser for you and sets you up
#  for being able to do persistant storage fairly simply.
#
#  In short:  it trys to do almost all of the work for you...  Almost...

# 
# Define types of data by mib type, and translate into needed C code.
#

# We need to get some extra stuff into the variable declarations
# before sourcing the main mib2c.vartypes.conf file below.
type:		OCTETSTR
storage:	    char   *${name};
storage:	    size_t  ${name}Len;
varlenname:	StorageTmp->${name}Len
vartest:	  if (StorageTmp->${name} == NULL) {
vartest:	    config_perror(\"invalid specification for ${name}\");
vartest:	    return;
vartest:	  }
vartest:
action:	             tmpvar = StorageTmp->$name;
action:	             tmplen = StorageTmp->${name}Len;
action:	             memdup((u_char **) &StorageTmp->$name, var_val, var_val_len);
action:	             StorageTmp->${name}Len = var_val_len;
undo:	             SNMP_FREE(StorageTmp->${name});
undo:	             StorageTmp->${name} = tmpvar;
undo:	             StorageTmp->${name}Len = tmplen;
commit:		     SNMP_FREE(tmpvar);
sizeofstart:	
sizeofend:	Len
tmpvar:		char *
casttmp:	strdup((char *) tmpvar);
#
type:		INTEGER
storage:	    long    $name;
storageret:	&
varlenname:	tmpint
sizeofstart:	sizeof(
sizeofend:	)
tmpvar:		int
action:	             tmpvar = StorageTmp->$name;
action:	             StorageTmp->${name} = *((long *) var_val);
undo:	             StorageTmp->${name} = tmpvar;
casttmp:	tmpvar;
#
type:		UNSIGNED32
storage:	    unsigned long    $name;
storageret:	&
varlenname:	tmpint
sizeofstart:	sizeof(
sizeofend:	)
tmpvar:		int
action:	             tmpvar = StorageTmp->$name;
action:	             StorageTmp->${name} = *((unsigned long *) var_val);
undo:	             StorageTmp->${name} = tmpvar;
casttmp:	tmpvar;
#
type:		OBJECTID
storage:	    oid     *$name;
storage:	    size_t   ${name}Len;
varlenname:	StorageTmp->${name}Len
vartest:	  if (StorageTmp->${name} == NULL) {
vartest:	    config_perror(\"invalid specification for ${name}\");
vartest:	    return;
vartest:	  }
vartest:
action:	             tmpvar = StorageTmp->$name;
action:	             tmplen = StorageTmp->${name}Len;
action:	             memdup((u_char **) &StorageTmp->$name, var_val, var_val_len);
action:	             StorageTmp->${name}Len = var_val_len/sizeof(oid);
undo:	             SNMP_FREE(StorageTmp->${name});
undo:	             StorageTmp->${name} = tmpvar;
undo:	             StorageTmp->${name}Len = tmplen;
commit:		     SNMP_FREE(tmpvar);
sizeofstart:	
sizeofend:	Len
tmpvar:		oid *
casttmp:	(oid *) tmpvar;
freetmp:	SNMP_FREE(tmpvar);
#
type:		COUNTER64
storage:	    struct counter64 $name;
varlenname:	tmpint
sizeofstart:	sizeof(
sizeofend:	)
tmpvar:		struct counter64 *
casttmp:	(struct counter64 *) tmpvar;

############################################################################
# source variable typing information:
include: mib2c.vartypes.conf

############################################################################
# The .h file
############################################################################
type:	code-dot-h
code:	/* This file was generated by mib2c and is intended for use as a mib module
code:	  for the ucd-snmp snmpd agent. */
code:
code:	#ifndef _MIBGROUP_${OUTPUTNAME}_H
code:	#define _MIBGROUP_${OUTPUTNAME}_H
code:	
code:	/* we may use header_complex from the header_complex module */
code:	
code:	config_require(header_complex)
code:
code:	/* our storage structure(s) */
code:	$variables{'code-structure-per-table'}{'processed'}
code:
code:	/* enum definitions from the covered mib sections */
code:
code:	$variables{'code-enums'}{'processed'}
code:
code:	/* function prototypes */
code:	
code:	void   init_$outputName(void);
code:	$variables{'code-var-table-decl'}{'processed'}
code:	$variables{'code-write-func-decl'}{'processed'}
code:	$variables{'code-write-rowstatus-decl'}{'processed'}
code:	
code:	#endif /* _MIBGROUP_${OUTPUTNAME}_H */

#
# Structure definition, one per table
#
type:		code-structure-per-table
processtable:	code-structure-per-table

code:	struct ${vtable}_data {
code:	$variables{$vtable}{'code-structure'}{'processed'}
code:	};

#
# Structure storage arrays, one per table
#
type:		code-structure-storage
processtable:	code-structure-storage

code:	static struct header_complex_index *${vtable}Storage = NULL;

#
# Structure definition line.
#
type:	code-structure
process: code-structure

code:	" . eval ("\"$variables{$mib->{'type'}}{'storage'}\"") . "
#$variables{$i}{'code'}\""evalstr(
#
# ENUM definitions
#
type:		code-enums
process:	code-enums
skipif: $mib->{'textualConvention'} eq "RowStatus" || $mib->{'textualConvention'} eq "StorageType"

code:	" . eval{ my ($i, $x); foreach $i (sort {$mib->{'enums'}{$a} <=> $mib->{'enums'}{$b}} keys(%{$mib->{'enums'}})) { $x .= sprintf("#define %-40s %d\n","${NAME}_" . uc($i),$mib->{'enums'}{$i}); } $x; } . "

############################################################################
# The .c file, top
############################################################################
type:	code-main-part
code:	/* This file was generated by mib2c and is intended for use as
code:	   a mib module for the ucd-snmp snmpd agent. */
code:	
code:	/* This should always be included first before anything else */
code:	#include <config.h>
code:	#if HAVE_STDLIB_H
code:	#include <stdlib.h>
code:	#endif
code:	#if HAVE_STRING_H
code:	#include <string.h>
code:	#else
code:	#include <strings.h>
code:	#endif
code:	
code:	/* minimal include directives */
code:	#include \"mibincl.h\"
code:	#include \"header_complex.h\"
code:	#include \"$outputName.h\"
code:	#include \"snmp-tc.h\"
code:	
code:	/* 
code:	 * ${outputName}_variables_oid:
code:	 *   this is the top level oid that we want to register under.  This
code:	 *   is essentially a prefix, with the suffix appearing in the
code:	 *   variable below.
code:	 */
code:	
code:	oid ${outputName}_variables_oid[] = { $commaoid };
code:	
code:	/* 
code:	 * variable$varlen ${outputName}_variables:
code:	 *   this variable defines function callbacks and type return information 
code:	 *   for the $outputName mib section 
code:	 */
code:	
code:	struct variable$varlen ${outputName}_variables[] = {
code:	/*  magic number        , variable type , ro/rw , callback fn  , L, oidsuffix */
code:	$variables{'variable-structure-info'}{'processed'}
code:	};
code:	/*    (L = length of the oidsuffix) */
code:	
code:	/* global storage of our data, saved in and configured by header_complex() */
code:	$variables{'code-structure-storage'}{'processed'}
code:
code:	/*
code:	 * init_$outputName():
code:	 *   Initialization routine.  This is called when the agent starts up.
code:	 *   At a minimum, registration of your variables should take place here.
code:	 */
code:	void init_$outputName(void) {
code:	  DEBUGMSGTL((\"$outputName\", \"initializing...  \"));
code:	
code:	  /* register ourselves with the agent to handle our mib tree */
code:	  REGISTER_MIB(\"$outputName\", ${outputName}_variables, variable$varlen,\
code:	               ${outputName}_variables_oid);
code:
code:	  /* register our config handler(s) to deal with registrations */
code:	$variables{'code-parser-registration'}{'processed'}
code:
code:	  /* we need to be called back later to store our data */
code:	  snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_STORE_DATA,
code:	                         store_$outputName, NULL);
code:	
code:	  /* place any other initialization junk you need here */
code:	
code:	  DEBUGMSGTL((\"$outputName\", \"done.\\n\"));
code:	}
code:	
code:	$variables{'code-parser'}{'processed'}
code:	
code:	$variables{'code-var_table'}{'processed'}
code:
code:	$variables{'code-write-func'}{'processed'}
code:
code:	$variables{'code-write-rowstatus'}{'processed'}

############################################################################
# var_ function for tables, which is handled specially and used above
#
#   Note: $vtable is set to the table name in the processtable loop.
############################################################################

#
# header file defs first
#
type:		code-var-table-decl
processtable:	code-var-table-decl

code:	FindVarMethod var_$vtable;
code:	void parse_$vtable(const char *, char *);
code:	SNMPCallback store_$vtable;

#
# .conf Parser Code per table
#
type:		code-parser-registration
processtable:	code-parser-registration
code:	  snmpd_register_config_handler(\"$vtable\", parse_$vtable, NULL,
code:	                                \"HELP STRING\");

type:		code-varlist-add
process:	code-varlist-add
skipif:		$variables{$vroutine}{$name}{'isanindex'} != 1
code:	  snmp_varlist_add_variable(&vars, NULL, 0, $variables{$mib->{type}}{asnType}, ($variables{$mib->{type}}{'cast'}) thedata->$name, $variables{$mib->{type}}{'sizeofstart'}thedata->$name$variables{$mib->{type}}{'sizeofend'}); /* $name */

type:		code-parser
processtable:	code-parser

code:	/* 
code:	 * ${vtable}_add(): adds a structure node to our data set 
code:	 */
code:	int
code:	${vtable}_add(struct ${vtable}_data *thedata) {
code:	  struct variable_list *vars = NULL;
code:
code:	  DEBUGMSGTL((\"$outputName\", \"adding data...  \"));
code:	 /* add the index variables to the varbind list, which is 
code:	    used by header_complex to index the data */
code:
code:	$variables{$vtable}{'code-varlist-add'}{'processed'}
code:
code:	  header_complex_add_data(&${vtable}Storage, vars, thedata);
code:	  DEBUGMSGTL((\"$vtable\",\"registered an entry\\n\"));
code:	
code:	  DEBUGMSGTL((\"$outputName\", \"done.\\n\"));
code:	  return SNMPERR_SUCCESS;
code:	}
code:
code:	/*
code:	 * parse_$vtable():
code:	 *   parses .conf file entries needed to configure the mib.
code:	 */
code:	void
code:	parse_$vtable(const char *token, char *line) {
code:	  size_t tmpint;
code:	  struct ${vtable}_data *StorageTmp = SNMP_MALLOC_STRUCT(${vtable}_data);
code:	  struct variable_list *vars = NULL;
code:
code:	    DEBUGMSGTL((\"$outputName\", \"parsing config...  \"));
code:
code:	  if (StorageTmp == NULL) {
code:	    config_perror(\"malloc failure\");
code:	    return;
code:	  }
code:
code:	$variables{$vtable}{'code-parser-sections'}{'processed'}
code:
code:	  ${vtable}_add(StorageTmp);
code:	    
code:	  DEBUGMSGTL((\"$outputName\", \"done.\\n\"));
code:	}
code:	
code:	
code:	/*
code:	 * store_$vtable():
code:	 *   stores .conf file entries needed to configure the mib.
code:	 */
code:	int
code:	store_$vtable(int majorID, int minorID, void *serverarg, void *clientarg) {
code:	  char line[SNMP_MAXBUF];
code:	  char *cptr;
code:	  size_t tmpint;
code:	  struct ${vtable}_data *StorageTmp;
code:	  struct header_complex_index *hcindex;
code:	
code:	  DEBUGMSGTL((\"$outputName\", \"storing data...  \"));
code:	
code:	  for(hcindex=${vtable}Storage; hcindex != NULL; 
code:	      hcindex = hcindex->next) {
code:	    StorageTmp = (struct ${vtable}_data *) hcindex->data;
code:	
code:	/*   XXX:  if (StorageTmp->${vtable}StorageType == ST_NONVOLATILE) { */
code:
code:	        memset(line,0,sizeof(line));
code:	        strcat(line, \"$vtable \");
code:	        cptr = line + strlen(line);
code:	
code:	$variables{$vtable}{'code-persistent-sections'}{'processed'}
code:
code:	    snmpd_store_config(line);
code:	/*   } */
code:	  }
code:	  DEBUGMSGTL((\"$outputName\", \"done.\\n\"));
code:	  return SNMPERR_SUCCESS;
code:	}

# individual sections for the parser
type:		code-parser-sections
process:	code-parser-sections
#skipif:		$mib->{'access'} =~ /NoAccess/
skipif:			$mib->{'label'} =~ /(Entry|Table)$/
code:	  line = read_config_read_data($variables{$mib->{type}}{asnType}, line, &StorageTmp->$name, &" . eval ("\"$variables{$mib->{type}}{varlenname}\"") . ");
code:	" . eval ("\"$variables{$mib->{type}}{vartest}\"") . "

#
# .conf persistent save Code per table
#
type:		code-persistent-sections
process:	code-persistent-sections
#skipif:		$mib->{'access'} =~ /NoAccess/
skipif:			$mib->{'label'} =~ /(Entry|Table)$/
code:	    cptr = read_config_store_data($variables{$mib->{type}}{asnType}, cptr, &StorageTmp->$name, &" . eval ("\"$variables{$mib->{type}}{varlenname}\"") . ");

#
# Code code per table
#
type:		code-var_table
processtable:	code-var_table

code:	/*
code:	 * var_$vtable():
code:	 *   Handle this table separately from the scalar value case.
code:	 *   The workings of this are basically the same as for var_$outputName above.
code:	 */
code:	unsigned char *
code:	var_$vtable(struct variable *vp,
code:	    	    oid     *name,
code:	    	    size_t  *length,
code:	    	    int     exact,
code:	    	    size_t  *var_len,
code:	    	    WriteMethod **write_method)
code:	{
code:
code:	struct ${vtable}_data *StorageTmp = NULL;
code:	
code:	  DEBUGMSGTL((\"$outputName\", \"var_$vtable: Entering...  \\n\"));
code:	  /* 
code:	   * this assumes you have registered all your data properly
cdoe:	   * with header_complex_add() somewhere before this
code:	   */
code:	  if ((StorageTmp =
code:	       header_complex(${vtable}Storage, vp,name,length,exact,
code:	                           var_len,write_method)) == NULL)
code:	    return NULL;
code:	
code:	  /* 
code:	   * this is where we do the value assignments for the mib results.
code:	   */
code:	  switch(vp->magic) {\n\n
code:	$variables{$vtable}{'code-case-statements'}{'processed'}
code:	    default:
code:	      ERROR_MSG(\"\");
code:	  }
code:	  return NULL;
code:	}


############################################################################
# case statement sections
############################################################################
type:		code-case-statements
process:	code-case-statements
skipif:		$mib->{'access'} =~ /NoAccess/

code:		    case $NAME:
code:		        " . (($mib->{'access'} =~ /ReadWrite|WriteOnly|Create/) ? "*write_method = write_$mib->{label};" : "") . "
code:		        *var_len = $variables{$mib->{'type'}}{'sizeofstart'}StorageTmp->$mib->{label}$variables{$mib->{'type'}}{'sizeofend'};
code:		        return (u_char *) $variables{$mib->{'type'}}{'storageret'}StorageTmp->$mib->{label};
code:		

############################################################################
# storage structure information
############################################################################
type:		variable-structure-info
process:	variable-structure-info
skipif:		$mib->{'access'} =~ /NoAccess/
code:		" . sprintf("#define   %-20s  $count", $NAME) . "
code:		" . sprintf("  { %-20s, %-14s, %-6.6s, %s, %d, { %s } },", $NAME, $variables{$mib->{'type'}}{'asnType'}, $accessToUCD{$mib->{'access'}}, "var_$vroutine", $depth-1, $subid) . "

############################################################################
# write function definition, also appended to the end of the .c file.
############################################################################
#
# Header info: declair write functions for set processing
#
process:	code-write-func-decl
type:		code-write-func-decl
skipif:		$mib->{'access'} !~ /Write|Create/
code:		WriteMethod write_$name;
#
# C code
#
type:		code-write-func
process:	code-write-func
skipif:		$mib->{'textualConvention'} eq "RowStatus" || $mib->{'access'} !~ /Write|Create/
code:	int
code:	write_$name(int      action,
code:	            u_char   *var_val,
code:	            u_char   var_val_type,
code:	            size_t   var_val_len,
code:	            u_char   *statP,
code:	            oid      *name,
code:	            size_t    name_len)
code:	{
code:	  static $variables{$mib->{'type'}}{tmpvar} tmpvar;
code:	  struct ${vroutine}_data *StorageTmp = NULL;
code:	  static size_t tmplen;
code:	  size_t newlen=name_len - (sizeof(${outputName}_variables_oid)/sizeof(oid) + $depth - 1);
code:
code:	  DEBUGMSGTL((\"$outputName\", \"write_$name entering action=%d...  \\n\", action));
code:	  if ((StorageTmp =
code:	       header_complex(${vroutine}Storage, NULL,
code:	                      &name[sizeof(${outputName}_variables_oid)/sizeof(oid) + $depth - 1], 
code:	                      &newlen, 1, NULL, NULL)) == NULL)
code:	      return SNMP_ERR_NOSUCHNAME; /* remove if you support creation here */
code:	
code:	  switch ( action ) {
code:	        case RESERVE1:
code:	          if (var_val_type != $variables{$mib->{'type'}}{asnType}){
code:	              fprintf(stderr, \"write to $name not $variables{$mib->{'type'}}{asnType}\\n\");
code:	              return SNMP_ERR_WRONGTYPE;
code:	          }
code:	          break;
code:	
code:	        case RESERVE2:
code:	             /* memory reseveration, final preparation... */
code:	          break;
code:	
code:	        case FREE:
code:	             /* Release any resources that have been allocated */
code:	          break;
code:	
code:	        case ACTION:
code:	             /* The variable has been stored in $variables{$mib->{'type'}}{variable} for
code:	             you to use, and you have just been asked to do something with
code:	             it.  Note that anything done here must be reversable in the UNDO case */
code:		".eval ("\"$variables{$mib->{type}}{action}\"")."
code:	          break;
code:	
code:	        case UNDO:
code:	             /* Back out any changes made in the ACTION case */
code:		".eval ("\"$variables{$mib->{type}}{undo}\"")."
code:	          break;
code:	
code:	        case COMMIT:
code:	             /* Things are working well, so it's now safe to make the change
code:	             permanently.  Make sure that anything done here can't fail! */
code:		".eval ("\"$variables{$mib->{'type'}}{'commit'}\"")."
code:	          break;
code:	  }
code:	  return SNMP_ERR_NOERROR;
code:	}
code:
code:
############################################################################
# copy memory from varlist
############################################################################
type:		code-varlist-copy
process:	code-varlist-copy
skipif:		$variables{$vroutine}{$name}{'isanindex'} != 1
code:	            memdup((u_char **) &(StorageNew->$name), 
code:	                   vp->val.$variables{$mib->{'type'}}{variable},
code:	                   vp->val_len);
code:	            StorageNew->${name}Len = vp->val_len;
code:	            vp = vp->next_variable;
############################################################################
# add null pointers to a varlist; value to be parsed later
############################################################################
type:		code-varlist-add-null
process:	code-varlist-add-null
skipif:		$variables{$vroutine}{$name}{'isanindex'} != 1
code:	  	  snmp_varlist_add_variable(&vars, NULL, 0, $variables{$mib->{'type'}}{asnType}, NULL, 0); /* $name */
############################################################################
# write function definition for a RowStatus object, 
#   - allows for creation/deletion.
############################################################################
#
# Header info: declair write functions for set processing
#
process:	code-write-rowstatus-decl
type:		code-write-rowstatus-decl
skipif:		$mib->{'textualConvention'} ne "RowStatus"
code:		WriteMethod write_$name;
#
# code
#
type:		code-write-rowstatus
process:	code-write-rowstatus
skipif:		$mib->{'textualConvention'} ne "RowStatus"
code:	int
code:	write_$name(int      action,
code:	            u_char   *var_val,
code:	            u_char   var_val_type,
code:	            size_t   var_val_len,
code:	            u_char   *statP,
code:	            oid      *name,
code:	            size_t    name_len)
code:	{
code:	  struct ${vroutine}_data *StorageTmp = NULL;
code:	  static struct ${vroutine}_data *StorageNew, *StorageDel;
code:	  size_t newlen=name_len - (sizeof(${vroutine}_variables_oid)/sizeof(oid) + 3 - 1);
code:	  static int old_value;
code:	  int set_value;
code:	  static struct variable_list *vars, *vp;
code:	  struct header_complex_index *hciptr;
code:	  char who[MAX_OID_LEN], flagName[MAX_OID_LEN];
code:	
code:	  StorageTmp =
code:	    header_complex(${vroutine}Storage, NULL,
code:	                   &name[sizeof(${vroutine}_variables_oid)/sizeof(oid) + 3 - 1], 
code:	                   &newlen, 1, NULL, NULL);
code:	  
code:	  
code:	  if (var_val_type != ASN_INTEGER || var_val == NULL){
code:	    fprintf(stderr, \"write to $name not ASN_INTEGER\\n\");
code:	    return SNMP_ERR_WRONGTYPE;
code:	  }
code:	  set_value = *((long *) var_val);
code:	
code:	  /* check legal range, and notReady is reserved for us, not a user */
code:	  if (set_value < 1 || set_value > 6 || set_value == RS_NOTREADY)
code:	    return SNMP_ERR_INCONSISTENTVALUE;
code:	    
code:	  switch ( action ) {
code:	        case RESERVE1:
code:		  /* stage one: test validity */
code:	          if (StorageTmp == NULL) {
code:	            /* create the row now? */
code:	
code:	            /* ditch illegal values now */
code:	            if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE)
code:	              return SNMP_ERR_INCONSISTENTVALUE;
code:	    
code:	            /* destroying a non-existent row is actually legal */
code:	            if (set_value == RS_DESTROY) {
code:	              return SNMP_ERR_NOERROR;
code:	            }
code:	
code:	            /* illegal creation values */
code:	            if (set_value == RS_ACTIVE || set_value == RS_NOTINSERVICE) {
code:	              return SNMP_ERR_INCONSISTENTVALUE;
code:	            }
code:	          } else {
code:	            /* row exists.  Check for a valid state change */
code:	            if (set_value == RS_CREATEANDGO || set_value == RS_CREATEANDWAIT) {
code:	              /* can't create a row that exists */
code:	              return SNMP_ERR_INCONSISTENTVALUE;
code:	            }
code:		    /* XXX: interaction with row storage type needed */
code:	          }
code:	          break;
code:	
code:	
code:	        case RESERVE2:
code:	          /* memory reseveration, final preparation... */
code:	          if (StorageTmp == NULL) {
code:	            /* creation */
code:	            vars = NULL;
code:	
code:	$variables{'code-varlist-add-null'}{'processed'}
code:	                    
code:	            if (header_complex_parse_oid(&(name[sizeof(${vroutine}_variables_oid)/sizeof(oid)+2]), newlen,
code:	                                         vars) != SNMPERR_SUCCESS) {
code:	              /* XXX: free, zero vars */
code:	              return SNMP_ERR_INCONSISTENTNAME;
code:	            }
code:	            vp = vars;
code:	
code:	            StorageNew = SNMP_MALLOC_STRUCT(${vroutine}_data);
code:	$variables{'code-varlist-copy'}{'processed'}
code:	
code:	
code:	            /* XXX: fill in default row values here into StorageNew */
code:	
code:	            StorageNew->$name = set_value;
code:	            /* XXX: free, zero vars, no longer needed? */
code:	          }
code:	          
code:	          break;
code:	
code:	
code:	        case FREE:
code:	          /* XXX: free, zero vars */
code:	          /* Release any resources that have been allocated */
code:	          break;
code:	
code:	
code:	        case ACTION:
code:	             /* The variable has been stored in set_value for you to
code:	             use, and you have just been asked to do something with
code:	             it.  Note that anything done here must be reversable in
code:	             the UNDO case */
code:	             
code:	             if (StorageTmp == NULL) {
code:	               /* row creation, so add it */
code:	               if (StorageNew != NULL)
code:	                 ${vroutine}_add(StorageNew);
code:	               /* XXX: ack, and if it is NULL? */
code:	             } else if (set_value != RS_DESTROY) {
code:	               /* set the flag? */
code:	               old_value = StorageTmp->$name;
code:	               StorageTmp->$name = *((long *) var_val);
code:	             } else {
code:	               /* destroy...  extract it for now */
code:	               hciptr =
code:	                 header_complex_find_entry(${vroutine}Storage,
code:	                                           StorageTmp);
code:	               StorageDel =
code:	                 header_complex_extract_entry(&${vroutine}Storage,
code:	                                              hciptr);
code:	             }
code:	          break;
code:	
code:	
code:	        case UNDO:
code:	             /* Back out any changes made in the ACTION case */
code:	             if (StorageTmp == NULL) {
code:	               /* row creation, so remove it again */
code:	               hciptr =
code:	                 header_complex_find_entry(${vroutine}Storage,
code:	                                           StorageTmp);
code:	               StorageDel =
code:	                 header_complex_extract_entry(&${vroutine}Storage,
code:	                                              hciptr);
code:	               /* XXX: free it */
code:	             } else if (StorageDel != NULL) {
code:	               /* row deletion, so add it again */
code:	               ${vroutine}_add(StorageDel);
code:	             } else {
code:	               StorageTmp->$name = old_value;
code:	             }
code:	          break;
code:	
code:	
code:	        case COMMIT:
code:	             /* Things are working well, so it's now safe to make the change
code:	             permanently.  Make sure that anything done here can't fail! */
code:	          if (StorageDel != NULL) {
code:	            StorageDel = 0;
code:	            /* XXX: free it, its dead */
code:	          } else {
code:	            if (StorageTmp && StorageTmp->$name == RS_CREATEANDGO) {
code:	                StorageTmp->$name = RS_ACTIVE;
code:	            } else if (StorageTmp &&
code:	                       StorageTmp->$name == RS_CREATEANDWAIT) {
code:	                StorageTmp->$name = RS_NOTINSERVICE;
code:	            }
code:	          }
code:	          break;
code:	  }
code:	  return SNMP_ERR_NOERROR;
code:	}
code:	
