/********************************************************************
 * 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 */
Example #3
0
/********************************************************************
* 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 */
Example #4
0
/********************************************************************
* 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 */
Example #5
0
/********************************************************************
* 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 */