| # 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: 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: /* 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(char *, char *); |
| |
| # |
| # .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(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: void |
| code: store_$vtable(void) { |
| 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: memset(line,0,sizeof(line)); |
| code: |
| code: strcat(line, \"$vtable\"); |
| code: cptr = line + strlen(line); |
| code: |
| code: for(hcindex=${vtable}Storage; hcindex != NULL; |
| code: hcindex = hcindex->next) { |
| code: StorageTmp = (struct ${vtable}_data *) hcindex->data; |
| code: |
| code: $variables{$vtable}{'code-persistent-sections'}{'processed'} |
| code: |
| code: snmpd_store_config(line); |
| code: } |
| code: DEBUGMSGTL((\"$outputName\", \"done.\\n\")); |
| code: } |
| |
| # individual sections for the parser |
| type: code-parser-sections |
| process: code-parser-sections |
| skipif: $mib->{'access'} =~ /NoAccess/ |
| |
| 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/ |
| 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: 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: } |
| code: break; |
| code: } |
| code: return SNMP_ERR_NOERROR; |
| code: } |
| code: |