/******************************************************************** * FUNCTION y_starter_starter_get_load_invoke * * RPC invocation phase * All constraints have passed at this point. * Call device instrumentation code in this function. * * INPUTS: * see agt/agt_rpc.h for details * * RETURNS: * error status ********************************************************************/ static status_t y_starter_starter_get_load_invoke ( ses_cb_t *scb, rpc_msg_t *msg, xml_node_t *methnode) { status_t res = NO_ERR; /* remove the next line if scb is used */ (void)scb; /* remove the next line if msg is used */ (void)msg; /* remove the next line if methnode is used */ (void)methnode; /* invoke your device instrumentation code here */ /*********************** THIS PART IS ADDED MANUALLY BY LEVI *************************/ //--------- GET LOAD DATA ---------------- //it looks like this: "0.01 0.14 0.12 1/309 6531" FILE *fp; int status; char load[30]; //open the command for reading fp = popen("cat /proc/loadavg", "r"); if(fp == NULL) { log_info("\nFailed to get LOAD\n"); } else { while(fgets(load, sizeof(load)-1, fp) != NULL) { log_info("\nRead data from cli: %s\n", load); } //closing pclose(fp); } //########################################## int numberOfLoadParams = 5; char *load_params[numberOfLoadParams]; int n=0; int nn; char *ds = strdup(load); load_params[n]=strtok(ds, " "); //log_info("load_params[%d]:%s",n,load_params[n]); while(load_params[n] && (n < (numberOfLoadParams-1))) { load_params[++n] = strtok(NULL, " "); // log_info("[LOG]load_params[%d]:%s",n,load_params[n]); } val_value_t *childval = NULL; childval = agt_make_list( obj_find_child(starter_get_load_obj,y_starter_M_starter,"output"), y_starter_N_load, &res); if(childval != NULL) { log_info("\nList found and initialized"); } val_value_t *a = NULL; /* char loadOne[40] = "load_One";*/ a = agt_make_leaf( childval->obj, y_starter_N_loadOne, (const xmlChar*)load_params[0], &res); if(a!=NULL) { log_info("\nloadOne filled with "); log_info(load_params[0]); val_add_child(a,childval); } else { return res; } /* char loadFive[40] = "load_Five";*/ a = agt_make_leaf( childval->obj, y_starter_N_loadFive, (const xmlChar*)load_params[1], &res); if(a!=NULL) { log_info("\nloadFive filled with "); log_info(load_params[1]); val_add_child(a,childval); } else { return res; } /* char loadFifteen[40] = "load_Fifteen";*/ a = agt_make_leaf( childval->obj, y_starter_N_loadFifteen, (const xmlChar*)load_params[2], &res); if(a!=NULL) { log_info("\nloadFifteen filled with "); log_info(load_params[2]); val_add_child(a,childval); } else { return res; } /* char processesCE[40] = "processesCurrentlyExists";*/ a = agt_make_leaf( childval->obj, y_starter_N_processesCurrentlyExists, (const xmlChar*)load_params[3], &res); if(a!=NULL) { log_info("\nprocessesCE filled with "); log_info(load_params[3]); val_add_child(a,childval); } else { return res; } /*log_info("PID: %s", load_params[4]);*/ //we need to remove the trailing \n from the end char* pid = strtok(load_params[4],"\n"); a = agt_make_leaf( childval->obj, y_starter_N_pid, (const xmlChar*)pid, &res); if(a!=NULL) { log_info("\npid filled with "); log_info(pid); val_add_child(a,childval); } else { return res; } free(ds); dlq_enque((void*)childval,&(msg->rpc_dataQ)); /* // ------------------------ CREATING A CUSTOM RPC REPLY ------------------------------- //declare a val_value_t * paramter val_value_t *rpc_output = NULL; //making a leaf // 1.param -> we need to find the corresponding output element defined in the yang // starter_get_load_obj is created automatically, since we have a get_load rpc in our module called starter -> starter_get_load_obj // y_starter_M_starter corresponds to the module (you need to modify both strings 'starter' to your module name) // "output" -> is the output part of the rpc (leave unmodified) // 2.param -> y_yourModuleName_N_leafNodeInYourRPCOUTPUT // 3.param -> the message you want to send (should be xmlChar*, char, char*) // 4. param -> the res variable which is returned by default rpc_output = agt_make_leaf( obj_find_child(starter_get_load_obj,y_starter_M_starter,"output"), y_starter_N_load, load, &res); //check that we could create correctly our RPC reply message if (rpc_output!=NULL) { //if yes -> put that to the rpc-reply (only rpc_output variable should be modified) dlq_enque((void*)rpc_output,&(msg->rpc_dataQ)); } //if, however, something went wrong during creating rpc-reply, we print it into the log else { log_error( "\nError: make leaf failed (%s), cannot send " "<load> rpc_reply", get_error_string(res)); } //====================================================================================== */ /********************************** END OF LEVI **************************************/ return res; } /* y_starter_starter_get_load_invoke */
/******************************************************************** * FUNCTION send_lock_pdu_to_server * * Send a <lock> or <unlock> operation to the server * * INPUTS: * server_cb == server control block to use * lockcb == lock control block to use within server_cb * islock == TRUE for lock; FALSE for unlock * * RETURNS: * status *********************************************************************/ static status_t send_lock_pdu_to_server (server_cb_t *server_cb, lock_cb_t *lockcb, boolean islock) { obj_template_t *rpc, *input; mgr_rpc_req_t *req; val_value_t *reqdata, *targetval, *parmval; ses_cb_t *scb; status_t res; xmlns_id_t obj_nsid; req = NULL; reqdata = NULL; res = NO_ERR; if (LOGDEBUG) { log_debug("\nSending <%s> request", (islock) ? NCX_EL_LOCK : NCX_EL_UNLOCK); } if (islock) { rpc = ncx_find_object(get_netconf_mod(server_cb), NCX_EL_LOCK); } else { rpc = ncx_find_object(get_netconf_mod(server_cb), NCX_EL_UNLOCK); } if (!rpc) { return SET_ERROR(ERR_NCX_DEF_NOT_FOUND); } obj_nsid = obj_get_nsid(rpc); /* get the 'input' section container */ input = obj_find_child(rpc, NULL, YANG_K_INPUT); if (!input) { return SET_ERROR(ERR_NCX_DEF_NOT_FOUND); } /* construct a method + parameter tree */ reqdata = xml_val_new_struct(obj_get_name(rpc), obj_nsid); if (!reqdata) { log_error("\nError allocating a new RPC request"); return ERR_INTERNAL_MEM; } /* set the [un]lock/input/target node XML namespace */ targetval = xml_val_new_struct(NCX_EL_TARGET, obj_nsid); if (!targetval) { log_error("\nError allocating a new RPC request"); val_free_value(reqdata); return ERR_INTERNAL_MEM; } else { val_add_child(targetval, reqdata); } parmval = xml_val_new_flag(lockcb->config_name, obj_nsid); if (!parmval) { val_free_value(reqdata); return ERR_INTERNAL_MEM; } else { val_add_child(parmval, targetval); } scb = mgr_ses_get_scb(server_cb->mysid); if (!scb) { res = SET_ERROR(ERR_INTERNAL_PTR); } else { req = mgr_rpc_new_request(scb); if (!req) { res = ERR_INTERNAL_MEM; log_error("\nError allocating a new RPC request"); } else { req->data = reqdata; req->rpc = rpc; req->timeout = server_cb->timeout; } } /* if all OK, send the RPC request */ if (res == NO_ERR) { if (LOGDEBUG2) { log_debug2("\nabout to send RPC request with reqdata:"); val_dump_value_max(reqdata, 0, server_cb->defindent, DUMP_VAL_LOG, server_cb->display_mode, FALSE, FALSE); } /* the request will be stored if this returns NO_ERR */ res = mgr_rpc_send_request(scb, req, yangcli_reply_handler); if (res == NO_ERR) { if (islock) { lockcb->lock_state = LOCK_STATE_REQUEST_SENT; } else { lockcb->lock_state = LOCK_STATE_RELEASE_SENT; } (void)uptime(&lockcb->last_msg_time); server_cb->locks_cur_cfg = lockcb->config_id; } } /* cleanup and set next state */ if (res != NO_ERR) { if (req) { mgr_rpc_free_request(req); } else if (reqdata) { val_free_value(reqdata); } } else { server_cb->state = MGR_IO_ST_CONN_RPYWAIT; } return res; } /* send_lock_pdu_to_server */
static status_t add_interfaces_state_entry(char* buf, val_value_t* interfaces_state_val) { /*objs*/ obj_template_t* interface_obj; obj_template_t* name_obj; obj_template_t* statistics_obj; obj_template_t* obj; /*vals*/ val_value_t* interface_val; val_value_t* name_val; val_value_t* statistics_val; val_value_t* val; status_t res=NO_ERR; boolean done; char* name; char* str; char* endptr; unsigned int i; uint64_t counter; int ret; char* counter_names_array[] = { "in-octets", "in-unicast-pkts", "in-errors", "in-discards", NULL/*"in-fifo"*/, NULL/*"in-frames"*/, NULL/*in-compressed*/, "in-multicast-pkts", "out-octets", "out-unicast-pkts", "out-errors", "out-discards", NULL/*"out-fifo"*/, NULL/*out-collisions*/, NULL/*out-carrier*/, NULL/*out-compressed*/ }; /* get the start of the interface name */ str = buf; while (*str && isspace(*str)) { str++; } if (*str == '\0') { /* not expecting a line with just whitespace on it */ return ERR_NCX_SKIPPED; } else { name = str++; } /* get the end of the interface name */ while (*str && *str != ':') { str++; } if (*str != ':') { /* expected e.g. eth0: ...*/ return ERR_NCX_SKIPPED; } else { *str=0; str++; } /* /interfaces-state/interface */ interface_obj = obj_find_child(interfaces_state_val->obj, "ietf-interfaces", "interface"); assert(interface_obj != NULL); interface_val = val_new_value(); if (interface_val == NULL) { return ERR_INTERNAL_MEM; } val_init_from_template(interface_val, interface_obj); val_add_child(interface_val, interfaces_state_val); /* /interfaces-state/interface/name */ name_obj = obj_find_child(interface_obj, "ietf-interfaces", "name"); assert(name_obj != NULL); name_val = val_new_value(); if (name_val == NULL) { return ERR_INTERNAL_MEM; } val_init_from_template(name_val, name_obj); res = val_set_simval_obj(name_val, name_obj, name); val_add_child(name_val, interface_val); res = val_gen_index_chain(interface_obj, interface_val); assert(res == NO_ERR); /* /interfaces-state/interface/statistics */ statistics_obj = obj_find_child(interface_obj, "ietf-interfaces", "statistics"); assert(statistics_obj != NULL); statistics_val = val_new_value(); if (statistics_val == NULL) { return ERR_INTERNAL_MEM; } val_init_from_template(statistics_val, statistics_obj); val_add_child(statistics_val, interface_val); done = FALSE; for(i=0;i<(sizeof(counter_names_array)/sizeof(char*));i++) { endptr = NULL; counter = strtoull((const char *)str, &endptr, 10); if (counter == 0 && str == endptr) { /* number conversion failed */ log_error("Error: /proc/net/dev number conversion failed."); return ERR_NCX_OPERATION_FAILED; } if(counter_names_array[i]!=NULL) { obj = obj_find_child(statistics_obj, "ietf-interfaces", counter_names_array[i]); assert(obj != NULL); val = val_new_value(); if (val == NULL) { return ERR_INTERNAL_MEM; } val_init_from_template(val, obj); VAL_UINT64(val) = counter; val_add_child(val, statistics_val); } str = (xmlChar *)endptr; if (*str == '\0' || *str == '\n') { break; } } return res; }
/******************************************************************** * FUNCTION parse_parm * * Parse, and fill one val_value_t struct during * processing of a parmset * * Error messages are printed by this function!! * Do not duplicate error messages upon error return * * * INPUTS: * tkc == token chain * val == container val to fill in * keepvals == TRUE to save existing parms in 'ps', as needed * FALSE to overwrite old parms in 'ps', as needed * * RETURNS: * status of the operation *********************************************************************/ static status_t parse_parm (tk_chain_t *tkc, val_value_t *val, boolean keepvals) { obj_template_t *obj; const xmlChar *modname; val_value_t *curparm, *newparm; status_t res; ncx_iqual_t iqual; boolean match, usewarning, isdefault; /* get the next token, which must be a TSTRING * representing the parameter name */ if (TK_CUR_TYP(tkc) != TK_TT_TSTRING) { res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "parameter name"); return res; } curparm = NULL; usewarning = ncx_warning_enabled(ERR_NCX_CONF_PARM_EXISTS); /* check if this TSTRING is a parameter in this parmset * make sure to always check for prefix:identifier * This is automatically processed in tk.c */ if (TK_CUR_MOD(tkc)) { modname = xmlns_get_module (xmlns_find_ns_by_prefix(TK_CUR_MOD(tkc))); if (modname) { curparm = val_find_child(val, modname, TK_CUR_VAL(tkc)); } } else { curparm = val_find_child(val, val_get_mod_name(val), TK_CUR_VAL(tkc)); } if (curparm) { obj = curparm->obj; } else { obj = obj_find_child(val->obj, TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); } if (!obj) { res = ERR_NCX_UNKNOWN_PARM; if (TK_CUR_MOD(tkc)) { log_error("\nError: parameter '%s:%s' not found", TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); } else { log_error("\nError: parameter '%s' not found", TK_CUR_VAL(tkc)); } ncx_conf_exp_err(tkc, res, "parameter name"); return res; } /* got a valid parameter name, now create a new parm * even if it may not be kept. There are corner-cases * that require the new value be parsed before knowing * if a parm value is a duplicate or not */ newparm = val_new_value(); if (!newparm) { res = ERR_INTERNAL_MEM; ncx_print_errormsg(tkc, NULL, res); return res; } val_init_from_template(newparm, obj); /* parse the parameter value */ res = parse_val(tkc, obj, newparm); if (res != NO_ERR) { val_free_value(newparm); return res; } /* check if a potential current value exists, or just * add the newparm to the parmset */ if (curparm) { isdefault = val_set_by_default(curparm); iqual = obj_get_iqualval(obj); if (iqual == NCX_IQUAL_ONE || iqual == NCX_IQUAL_OPT) { /* only one allowed, check really a match */ match = TRUE; if (val_has_index(curparm) && !val_index_match(newparm, curparm)) { match = FALSE; } if (!match) { val_add_child(newparm, val); } else if (isdefault) { dlq_remove(curparm); val_free_value(curparm); val_add_child(newparm, val); } else if (keepvals) { if (usewarning) { /* keep current value and toss new value */ log_warn("\nWarning: Parameter '%s' already exists. " "Not using new value\n", curparm->name); if (LOGDEBUG2) { val_dump_value(newparm, NCX_DEF_INDENT); log_debug2("\n"); } } val_free_value(newparm); } else { if (usewarning) { /* replace current value and warn old value tossed */ log_warn("\nconf: Parameter '%s' already exists. " "Overwriting with new value\n", curparm->name); if (LOGDEBUG2) { val_dump_value(newparm, NCX_DEF_INDENT); log_debug2("\n"); } } dlq_remove(curparm); val_free_value(curparm); val_add_child(newparm, val); } } else { /* mutliple instances allowed */ val_add_child(newparm, val); } } else { val_add_child(newparm, val); } return NO_ERR; } /* parse_parm */
/******************************************************************** * FUNCTION parse_val * * Parse, and fill one val_value_t struct during * processing of a text config file * * Error messages are printed by this function!! * Do not duplicate error messages upon error return * * The value name is the current token. * Based on the value typdef, the res of the tokens * comprising the value statement will be processed * * INPUTS: * tkc == token chain * obj == the object template struct to use for filling in 'val' * val == initialized value struct, without any value, * which will be filled in by this function * nsid == namespace ID to use for this value * valname == name of the value struct * * RETURNS: * status of the operation *********************************************************************/ static status_t parse_val (tk_chain_t *tkc, obj_template_t *obj, val_value_t *val) { obj_template_t *chobj; val_value_t *chval; const xmlChar *valname, *useval; typ_def_t *typdef; status_t res; ncx_btype_t btyp; boolean done; xmlns_id_t nsid; btyp = obj_get_basetype(obj); nsid = obj_get_nsid(obj); valname = obj_get_name(obj); typdef = obj_get_typdef(obj); /* check if there is an index clause expected */ if (typ_has_index(btyp)) { res = parse_index(tkc, obj, val, nsid); if (res != NO_ERR) { return res; } } /* get next token, NEWLINE is significant at this point */ res = adv_tk(tkc); if (res != NO_ERR) { return res; } /* the current token should be the value for a leaf * or a left brace for the start of a complex type * A NEWLINE is treated as if the user entered a * zero-length string for the value. (Unless the * base type is NCX_BT_EMPTY, in which case the NEWLINE * is the expected token */ if (typ_is_simple(btyp)) { /* form for a leaf is: foo [value] NEWLINE */ if (TK_CUR_TYP(tkc)==TK_TT_NEWLINE) { useval = NULL; } else { useval = TK_CUR_VAL(tkc); } res = val_set_simval(val, typdef, nsid, valname, useval); if (res != NO_ERR) { log_error("\nError: '%s' cannot be set to '%s'", valname, (TK_CUR_VAL(tkc)) ? TK_CUR_VAL(tkc) : EMPTY_STRING); if (btyp == NCX_BT_EMPTY) { ncx_conf_exp_err(tkc, res, "empty"); } else { ncx_conf_exp_err(tkc, res, "simple value string"); } return res; } /* get a NEWLINE unless current token is already a NEWLINE */ if (TK_CUR_TYP(tkc) != TK_TT_NEWLINE) { res = adv_tk(tkc); if (res != NO_ERR) { return res; } if (TK_CUR_TYP(tkc) != TK_TT_NEWLINE) { res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "\\n"); } } } else { /* complex type is foo { ... } or * foo index1 index2 { ... } * If there is an index, it was already parsed */ res = consume_tk(tkc, TK_TT_LBRACE); if (res != NO_ERR) { ncx_conf_exp_err(tkc, res, "left brace"); return res; } /* get all the child nodes specified for this complex type */ res = NO_ERR; done = FALSE; while (!done && res==NO_ERR) { /* start out looking for a child node name or a * right brace to end the sub-section */ if (tk_next_typ(tkc)==TK_TT_NEWLINE) { /* skip the NEWLINE token */ (void)adv_tk(tkc); } else if (tk_next_typ(tkc)==TK_TT_RBRACE) { /* found end of sub-section */ done = TRUE; } else { /* get the next token */ res = adv_tk(tkc); if (res != NO_ERR) { continue; } /* make sure cur token is an identifier string * if so, find the child node and call this function * recursively to fill it in and add it to * the parent 'val' */ if (TK_CUR_ID(tkc)) { /* parent 'typdef' must have a child with a name * that matches the current token vale */ chobj = obj_find_child(obj, TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); if (chobj) { chval = val_new_value(); if (!chval) { res = ERR_INTERNAL_MEM; ncx_print_errormsg(tkc, NULL, res); } else { val_init_from_template(chval, chobj); res = parse_val(tkc, chobj, chval); if (res == NO_ERR) { val_add_child(chval, val); } else { val_free_value(chval); } } } else { /* string is not a child name in this typdef */ res = ERR_NCX_DEF_NOT_FOUND; ncx_conf_exp_err(tkc, res, "identifier string"); } } else { /* token is not an identifier string */ res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "identifier string"); } } } /* end loop through all the child nodes */ /* expecting a right brace to finish the complex value */ if (res == NO_ERR) { res = consume_tk(tkc, TK_TT_RBRACE); if (res != NO_ERR) { ncx_conf_exp_err(tkc, res, "right brace"); return res; } } } return res; } /* parse_val */
/******************************************************************** * FUNCTION obj_dump_template * * Dump the contents of an obj_template_t struct for help text * * INPUTS: * obj == obj_template to dump help for * mode == requested help mode * nestlevel == number of levels from the top-level * that should be printed; 0 == all levels * indent == start indent count *********************************************************************/ void obj_dump_template (obj_template_t *obj, help_mode_t mode, uint32 nestlevel, uint32 indent) { const xmlChar *val, *keystr; obj_template_t *testobj; uint32 count, objnestlevel; char numbuff[NCX_MAX_NUMLEN]; boolean normalpass, neednewline; #ifdef DEBUG if (mode > HELP_MODE_FULL) { SET_ERROR(ERR_INTERNAL_VAL); return; } #endif if (obj == NULL) { /* could be called because disabled first child found */ return; } if (!obj_has_name(obj) || !obj_is_enabled(obj)) { return; } if (mode == HELP_MODE_NONE) { return; } objnestlevel = obj_get_level(obj); if (mode == HELP_MODE_BRIEF && nestlevel > 0 && objnestlevel > nestlevel) { return; } normalpass = (nestlevel && (objnestlevel > nestlevel)) ? FALSE : TRUE; if (obj->objtype == OBJ_TYP_RPCIO || obj->objtype == OBJ_TYP_RPC) { help_write_lines(obj_get_name(obj), indent, TRUE); count = 0; } else if (obj->objtype == OBJ_TYP_CASE) { count = obj_enabled_child_count(obj); } else { count = 2; } if (count > 1) { help_write_lines(obj_get_typestr(obj), indent, TRUE); help_write_lines((const xmlChar *)" ", 0, FALSE); help_write_lines(obj_get_name(obj), 0, FALSE); } neednewline = FALSE; switch (obj->objtype) { case OBJ_TYP_CONTAINER: case OBJ_TYP_LIST: case OBJ_TYP_CASE: case OBJ_TYP_RPC: case OBJ_TYP_RPCIO: case OBJ_TYP_NOTIF: break; default: /* print type and default for leafy and choice objects */ if (obj->objtype != OBJ_TYP_CHOICE) { help_write_lines((const xmlChar *)" [", 0, FALSE); help_write_lines((const xmlChar *) obj_get_type_name(obj), 0, FALSE); help_write_lines((const xmlChar *)"]", 0, FALSE); } if (mode != HELP_MODE_BRIEF) { val = obj_get_default(obj); if (val != NULL) { help_write_lines((const xmlChar *)" [d:", 0, FALSE); help_write_lines(val, 0, FALSE); help_write_lines((const xmlChar *)"]", 0, FALSE); } if (obj_is_key(obj)) { help_write_lines((const xmlChar *)" <Key>", 0, FALSE); } else if (obj_is_mandatory(obj)) { help_write_lines((const xmlChar *)" <Mandatory>", 0, FALSE); } } } if (normalpass) { val = obj_get_description(obj); if (val == NULL) { val = obj_get_alt_description(obj); } if (val != NULL) { switch (mode) { case HELP_MODE_BRIEF: if (obj->objtype == OBJ_TYP_RPC || obj->objtype == OBJ_TYP_NOTIF) { help_write_lines_max(val, indent+NCX_DEF_INDENT, TRUE, HELP_MODE_BRIEF_MAX); } break; case HELP_MODE_NORMAL: help_write_lines_max(val, indent+NCX_DEF_INDENT, TRUE, HELP_MODE_NORMAL_MAX); break; case HELP_MODE_FULL: help_write_lines(val, indent+NCX_DEF_INDENT, TRUE); break; default: SET_ERROR(ERR_INTERNAL_VAL); return; } } } switch (obj->objtype) { case OBJ_TYP_CONTAINER: switch (mode) { case HELP_MODE_BRIEF: neednewline = TRUE; break; case HELP_MODE_NORMAL: if (obj->def.container->presence) { help_write_lines((const xmlChar *)" (P)", 0, FALSE); } else { help_write_lines((const xmlChar *)" (NP)", 0, FALSE); } testobj = obj_get_default_parm(obj); if (testobj) { help_write_lines((const xmlChar *)"default parameter: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(obj_get_name(testobj), 0, FALSE); } break; case HELP_MODE_FULL: if (obj->def.container->presence) { help_write_lines((const xmlChar *)"presence: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(obj->def.container->presence, 0, FALSE); } testobj = obj_get_default_parm(obj); if (testobj) { help_write_lines((const xmlChar *)"default parameter: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(obj_get_name(testobj), 0, FALSE); } if (mode == HELP_MODE_FULL) { /*** add mustQ ***/; } break; default: SET_ERROR(ERR_INTERNAL_VAL); return; } obj_dump_datadefQ(obj->def.container->datadefQ, mode, nestlevel, indent+NCX_DEF_INDENT); break; case OBJ_TYP_ANYXML: /* nothing interesting in the typdef to report */ neednewline = TRUE; break; case OBJ_TYP_LEAF: switch (mode) { case HELP_MODE_BRIEF: break; case HELP_MODE_NORMAL: if (normalpass) { dump_typdef_data(obj, mode, indent+NCX_DEF_INDENT); } break; case HELP_MODE_FULL: dump_typdef_data(obj, mode, indent+NCX_DEF_INDENT); val = obj_get_units(obj); if (val) { help_write_lines((const xmlChar *)"units: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(val, 0, FALSE); } break; default: ; } break; case OBJ_TYP_LEAF_LIST: switch (mode) { case HELP_MODE_NORMAL: if (normalpass) { dump_typdef_data(obj, mode, indent+NCX_DEF_INDENT); } break; case HELP_MODE_FULL: dump_typdef_data(obj, mode, indent+NCX_DEF_INDENT); val = obj_get_units(obj); if (val) { help_write_lines((const xmlChar *)"units: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(val, 0, FALSE); } if (!obj->def.leaflist->ordersys) { help_write_lines((const xmlChar *)"ordered-by: user", indent+NCX_DEF_INDENT, TRUE); } else { help_write_lines((const xmlChar *)"ordered-by: system", indent+NCX_DEF_INDENT, TRUE); } if (obj->def.leaflist->minset) { help_write_lines((const xmlChar *)"min-elements: ", indent+NCX_DEF_INDENT, TRUE); snprintf(numbuff, sizeof(numbuff), "%u", obj->def.leaflist->minelems); help_write_lines((const xmlChar *)numbuff, 0, FALSE); } if (obj->def.leaflist->maxset) { help_write_lines((const xmlChar *)"max-elements: ", indent+NCX_DEF_INDENT, TRUE); snprintf(numbuff, sizeof(numbuff), "%u", obj->def.leaflist->maxelems); help_write_lines((const xmlChar *)numbuff, 0, FALSE); } break; default: ; } break; case OBJ_TYP_CHOICE: if (mode == HELP_MODE_BRIEF) { neednewline = TRUE; break; } count = obj_enabled_child_count(obj); if (count) { obj_dump_datadefQ(obj_get_datadefQ(obj), mode, nestlevel, indent+NCX_DEF_INDENT); } break; case OBJ_TYP_CASE: if (mode == HELP_MODE_BRIEF) { neednewline = TRUE; break; } count = obj_enabled_child_count(obj); if (count > 1) { obj_dump_datadefQ(obj_get_datadefQ(obj), mode, nestlevel, indent+NCX_DEF_INDENT); } else if (count == 1) { testobj = obj_first_child(obj); if (testobj) { obj_dump_template(testobj, mode, nestlevel, indent); } } /* else skip this case */ break; case OBJ_TYP_LIST: switch (mode) { case HELP_MODE_BRIEF: break; case HELP_MODE_NORMAL: case HELP_MODE_FULL: keystr = obj_get_keystr(obj); if (keystr != NULL) { help_write_lines((const xmlChar *)"key: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(keystr, 0, FALSE); } if (!obj->def.list->ordersys) { help_write_lines((const xmlChar *)"ordered-by: user", indent+NCX_DEF_INDENT, TRUE); } if (mode == HELP_MODE_NORMAL) { break; } if (obj->def.list->minset) { help_write_lines((const xmlChar *)"min-elements: ", indent+NCX_DEF_INDENT, TRUE); snprintf(numbuff, sizeof(numbuff), "%u", obj->def.list->minelems); help_write_lines((const xmlChar *)numbuff, 0, FALSE); } if (obj->def.list->maxset) { help_write_lines((const xmlChar *)"max-elements: ", indent+NCX_DEF_INDENT, TRUE); snprintf(numbuff, sizeof(numbuff), "%u", obj->def.list->maxelems); help_write_lines((const xmlChar *)numbuff, 0, FALSE); } break; default: ; } if (mode != HELP_MODE_BRIEF) { obj_dump_datadefQ(obj_get_datadefQ(obj), mode, nestlevel, indent+NCX_DEF_INDENT); } break; case OBJ_TYP_RPC: testobj = obj_find_child(obj, NULL, YANG_K_INPUT); if (testobj && obj_enabled_child_count(testobj)) { obj_dump_template(testobj, mode, nestlevel, indent+NCX_DEF_INDENT); } testobj = obj_find_child(obj, NULL, YANG_K_OUTPUT); if (testobj && obj_enabled_child_count(testobj)) { obj_dump_template(testobj, mode, nestlevel, indent+NCX_DEF_INDENT); } help_write_lines((const xmlChar *)"\n", 0, FALSE); break; case OBJ_TYP_RPCIO: if (mode != HELP_MODE_BRIEF) { testobj = obj_get_default_parm(obj); if (testobj && obj_is_enabled(testobj)) { help_write_lines((const xmlChar *)"default parameter: ", indent+NCX_DEF_INDENT, TRUE); help_write_lines(obj_get_name(testobj), 0, FALSE); } else { neednewline = FALSE; } } obj_dump_datadefQ(obj_get_datadefQ(obj), mode, nestlevel, indent+NCX_DEF_INDENT); break; case OBJ_TYP_NOTIF: obj_dump_datadefQ(obj_get_datadefQ(obj), mode, nestlevel, indent+NCX_DEF_INDENT); break; case OBJ_TYP_AUGMENT: case OBJ_TYP_USES: case OBJ_TYP_REFINE: default: SET_ERROR(ERR_INTERNAL_VAL); } if (neednewline) { help_write_lines(NULL, 0, TRUE); } } /* obj_dump_template */