/******************************************************************** * FUNCTION expand_alias * * Check if the first token is an alias name * If so, construct a new command line with the alias contents * * INPUT: * line == command line to check and possibly convert * res == address of return status * * OUTPUTS: * *res == return status (ERR_NCX_SKIPPED if nothing done) * * RETURNS: * pointer to malloced command string if *res==NO_ERR * NULL if *res==ERR_NCX_SKIPPED or some real error *********************************************************************/ xmlChar * expand_alias (xmlChar *line, status_t *res) { xmlChar *start, *p = line, *newline; alias_cb_t *alias; uint32 namelen, newlen; boolean done = FALSE; /* skip any leading whitespace; not expected from yangcli */ while (*p && xml_isspace(*p)) { p++; } if (*p == 0) { *res = ERR_NCX_SKIPPED; return NULL; } /* look for end of name */ start = p; if (!ncx_valid_fname_ch(*p++)) { *res = ERR_NCX_SKIPPED; return NULL; } while (*p && !done) { if (xml_isspace(*p)) { done = TRUE; } else if (!ncx_valid_name_ch(*p)) { *res = ERR_NCX_SKIPPED; return NULL; } else { p++; } } /* look for the alias */ namelen = (uint32)(p - start); alias = find_alias(start, namelen); if (alias == NULL) { *res = ERR_NCX_SKIPPED; return NULL; } /* replace the alias name with its contents and make a new string */ if (alias->value) { newlen = xml_strlen(p) + xml_strlen(alias->value); } else { newlen = xml_strlen(p); } newline = m__getMem(newlen + 1); if (newline == NULL) { *res = ERR_INTERNAL_MEM; return NULL; } start = newline; if (alias->value) { start += xml_strcpy(start, alias->value); } xml_strcpy(start, p); if (LOGDEBUG2) { log_debug2("\nExpanded alias '%s'; new line: '%s'", alias->name, newline); } *res = NO_ERR; return newline; } /* expand_alias */
/******************************************************************** * FUNCTION load_aliases * * Load the aliases from the specified filespec * * INPUT: * fspec == input filespec to use (NULL == default) * file_error == TRUE if the file must be found * FALSE if finding the default file and it * is not required to be present * RETURNS: * status *********************************************************************/ status_t load_aliases (const xmlChar *fspec, boolean file_error) { FILE *fp; xmlChar *fullspec, *buffer; status_t res = NO_ERR; buffer = m__getMem(NCX_MAX_LINELEN+1); if (buffer == NULL) { log_error("\nError: malloc failed\n"); return ERR_INTERNAL_MEM; } if (fspec == NULL) { fspec = get_aliases_file(); } fullspec = ncx_get_source(fspec, &res); if (res == NO_ERR && fullspec) { fp = fopen((const char *)fullspec, "r"); if (fp) { #define MAX_ALIAS_ERRORS 5 boolean done = FALSE; uint32 errorcnt = 0; while (!done) { char *retstr = fgets((char *)buffer, NCX_MAX_LINELEN+1, fp); if (retstr) { uint32 len = xml_strlen(buffer); if (len) { if (*buffer != '#' && *buffer != '\n') { if (buffer[len-1] == '\n') { buffer[len-1] = 0; } res = handle_alias_parm(buffer, TRUE, FALSE); if (res != NO_ERR) { if (++errorcnt == MAX_ALIAS_ERRORS) { log_error("\nError: skipping aliases; " "too many errors\n"); done = TRUE; } } } // else skip a newline or comment line } // else skip empty line } else { done = TRUE; } } fclose(fp); /* Save mtime of this aliases file */ res = update_def_yangcli_file_mtime (ALIASES_FILE, fullspec); } else if (file_error) { log_error("\nError: Aliases file '%s' could not be opened\n", fullspec); res = ERR_FIL_OPEN; } else if (LOGDEBUG) { log_debug("\nAliases file '%s' could not be opened\n", fullspec); } } else { log_error("\nError: Expand source '%s' failed (%s)", fspec, get_error_string(res)); } if (fullspec) { m__free(fullspec); } if (buffer) { m__free(buffer); } return res; } /* load_aliases */
/******************************************************************** * FUNCTION set_initial_transaction_id * * Set the last_transaction_id for the running config * Will check for sys:transaction-id leaf in config->root * * RETURNS: * status *********************************************************************/ static status_t set_initial_transaction_id (void) { cfg_template_t *cfg = cfg_get_config_id(NCX_CFGID_RUNNING); if (cfg == NULL) { return ERR_NCX_CFG_NOT_FOUND; } if (cfg->root == NULL) { return ERR_NCX_EMPTY_VAL; } agt_profile_t *profile = agt_get_profile(); status_t res = NO_ERR; boolean foundfile = FALSE; /* figure out which transaction ID file to use */ if (profile->agt_startup_txid_file == NULL) { /* search for the default startup-cfg.xml filename */ xmlChar *fname = ncxmod_find_data_file(NCX_DEF_STARTUP_TXID_FILE, FALSE, &res); if (fname == NULL || res != NO_ERR || *fname == 0) { /* need to set the default startup transaction ID file name */ log_debug("\nSetting initial transaction ID file to default"); if (fname) { m__free(fname); } res = NO_ERR; fname = agt_get_startup_filespec(&res); if (fname == NULL || res != NO_ERR) { if (res == NO_ERR) { res = ERR_NCX_OPERATION_FAILED; } log_error("\nFailed to set initial transaction ID file (%s)", get_error_string(res)); if (fname) { m__free(fname); } return res; } /* get dir part and append the TXID file name to it */ uint32 fnamelen = xml_strlen(fname); xmlChar *str = &fname[fnamelen - 1]; while (str >= fname && *str && *str != NCX_PATHSEP_CH) { str--; } if (*str != NCX_PATHSEP_CH) { log_error("\nFailed to set initial transaction ID file"); m__free(fname); return ERR_NCX_INVALID_VALUE; } /* copy base filespec + 1 for the path-sep-ch */ uint32 baselen = (uint32)(str - fname) + 1; uint32 newlen = baselen + xml_strlen(NCX_DEF_STARTUP_TXID_FILE); xmlChar *newstr = m__getMem(newlen + 1); if (newstr == NULL) { m__free(fname); return ERR_INTERNAL_MEM; } str = newstr; str += xml_strncpy(str, fname, baselen); xml_strcpy(str, NCX_DEF_STARTUP_TXID_FILE); m__free(fname); profile->agt_startup_txid_file = newstr; // pass off memory here } else { foundfile = TRUE; profile->agt_startup_txid_file = fname; // pass off memory here } } /* initialize the starting transaction ID in the config module */ res = agt_cfg_init_transactions(profile->agt_startup_txid_file, foundfile); if (res != NO_ERR) { log_error("\nError: cfg-init transaction ID failed (%s)", get_error_string(res)); } return res; } /* set_initial_transaction_id */
/******************************************************************** * FUNCTION tstamp_convert_to_utctime * * Check if the specified string is a valid dateTime or * date-and-time string is valid and if so, convert it * to * * INPUTS: * buff == pointer to buffer to check * isNegative == address of return negative date flag * res == address of return status * * OUTPUTS: * *isNegative == TRUE if a negative dateTime string is given * FALSE if no starting '-' sign found * *res == return status * * RETURNS: * malloced pointer to converted date time string * or NULL if some error *********************************************************************/ xmlChar * tstamp_convert_to_utctime (const xmlChar *timestr, boolean *isNegative, status_t *res) { assert(timestr && "timestr is NULL!"); assert(isNegative && "isNegative is NULL!"); assert(res && "res is NULL!"); *res = NO_ERR; struct tm convertedtime; memset(&convertedtime, 0x0, sizeof(struct tm)); if (*timestr == '-') { *isNegative = TRUE; timestr++; } else { *isNegative = FALSE; } xmlChar *buffer = NULL; const char *retptr = NULL; uint32 len = xml_strlen(timestr); if (len == 20) { /* could be in canonical form */ retptr = strptime((const char *)timestr, "%FT%TZ", &convertedtime); if (retptr && *retptr == '\0') { buffer = xml_strdup(timestr); if (!buffer) { *res = ERR_INTERNAL_MEM; return NULL; } else { return buffer; } } else { *res = ERR_NCX_INVALID_VALUE; return NULL; } } else if (len > 20) { retptr = strptime((const char *)timestr, "%FT%T", &convertedtime); if (retptr == NULL || *retptr == '\0') { *res = ERR_NCX_INVALID_VALUE; return NULL; } /* check is frac-seconds entered, and skip it */ if (*retptr == '.') { retptr++; if (!isdigit((int)*retptr)) { *res = ERR_NCX_INVALID_VALUE; return NULL; } retptr++; /* got a start digit */ while (isdigit((int)*retptr)) { retptr++; } } /* check if a timezone offset is present */ retptr = strptime(retptr, "%z", &convertedtime); if (retptr == NULL) { *res = ERR_NCX_INVALID_VALUE; return NULL; } /* check where retptr ended up */ if (*retptr == '\0') { /* OK read all the bytes */ ; } else if (*retptr == ':') { if (strcmp(retptr, ":00")) { /* the linux strptime function does * not process the 'time-minute' field in the * time string; since this is so rare * just treat as a special error */ *res = ERR_NCX_OPERATION_NOT_SUPPORTED; return NULL; } /* else time-minute field == '00' and no error */ } else { *res = ERR_NCX_INVALID_VALUE; return NULL; } buffer = m__getMem(TSTAMP_MIN_SIZE); if (!buffer) { *res = ERR_INTERNAL_MEM; return NULL; } time_t utime = mktime(&convertedtime); if (utime == (utime)-1) { *res = ERR_NCX_INVALID_VALUE; m__free(buffer); return NULL; } struct tm *curtime = gmtime(&utime); time_to_string(curtime, buffer); return buffer; } else { /* improper length */ *res = ERR_NCX_INVALID_VALUE; return NULL; } } /* tstamp_convert_to_utctime */
/******************************************************************** * FUNCTION xml_msg_gen_new_prefix * * Generate a new namespace prefix * * INPUTS: * msg == message to search and generate a prefix for * nsid == namespace ID to generate prefix for * retbuff == address of return buffer * buffsize == buffer size * OUTPUTS: * if *retbuff is NULL it will be created * else *retbuff is filled in with the new prefix if NO_ERR * * RETURNS: * status *********************************************************************/ status_t xml_msg_gen_new_prefix (xml_msg_hdr_t *msg, xmlns_id_t nsid, xmlChar **retbuff, uint32 buffsize) { const xmlChar *defpfix; xmlChar startch; int32 nlen, i; xmlChar numbuff[NCX_MAX_NUMLEN], *buff; xmlns_id_t testid; #ifdef DEBUG if (!msg || !retbuff) { return SET_ERROR(ERR_INTERNAL_PTR); } #endif if (*retbuff) { buff = *retbuff; } else { buff = m__getMem(NCX_MAX_NUMLEN+1); if (!buff) { return ERR_INTERNAL_MEM; } else { buffsize = NCX_MAX_NUMLEN+1; *retbuff = buff; } } /* first see if a default prefix was registered with the namespace * and use it if not already in the prefix map */ defpfix = xmlns_get_ns_prefix(nsid); if (defpfix && *defpfix) { testid = find_prefix_val(msg, defpfix); if (testid == 0 || testid==nsid) { if (xml_strlen(defpfix) < buffsize) { xml_strcpy(buff, defpfix); return NO_ERR; } else { return ERR_BUFF_OVFL; } } } /* default already in use for something else so generate a prefix */ nlen = snprintf((char *)numbuff, NCX_MAX_NUMLEN, "%u", (uint32)nsid); if (nlen < 0) { return ERR_NCX_INVALID_NUM; } if ((uint32)(nlen+2) >= buffsize) { return ERR_BUFF_OVFL; } /* copy the number to the prefix buffer w/ trailing zero */ for (i=0; i<=nlen; i++) { buff[i+1] = numbuff[i]; } /* set the start letter in the prefix buffer */ startch = 'n'; /* try to generate a unique prefix */ for (i=0; i<=MAX_PREFIX_TRIES; i++) { /* adjust the label value */ buff[0] = startch++; if (startch > 'z') { startch = 'a'; } /* check if the prefix is in use */ if (!find_prefix_val(msg, buff)) { return NO_ERR; } } return ERR_NCX_OPERATION_FAILED; } /* xml_msg_gen_new_prefix */