예제 #1
0
파일: load.c 프로젝트: pexip/os-autogen
static ag_bool
insertEnvVal(char * pzBuf, int bufSize, char const * pzName,
             char const * pzProgPath)
{
    char* pzDir = pzBuf;

    for (;;) {
        int ch = (int)*++pzName;
        if (! IS_VALUE_NAME_CHAR(ch))
            break;
        *(pzDir++) = (char)ch;
    }

    if (pzDir == pzBuf)
        return AG_FALSE;

    *pzDir = NUL;

    pzDir = getenv(pzBuf);

    /*
     *  Environment value not found -- skip the home list entry
     */
    if (pzDir == NULL)
        return AG_FALSE;

    if (strlen(pzDir) + 1 + strlen(pzName) >= bufSize)
        return AG_FALSE;

    sprintf(pzBuf, "%s%s", pzDir, pzName);
    return AG_TRUE;
}
예제 #2
0
파일: load.c 프로젝트: 1and1get2/tcpreplay
static bool
add_env_val(char * buf, int buf_sz, char const * name)
{
    char * dir_part = buf;

    for (;;) {
        int ch = (int)*++name;
        if (! IS_VALUE_NAME_CHAR(ch))
            break;
        *(dir_part++) = (char)ch;
    }

    if (dir_part == buf)
        return false;

    *dir_part = NUL;

    dir_part = getenv(buf);

    /*
     *  Environment value not found -- skip the home list entry
     */
    if (dir_part == NULL)
        return false;

    if (strlen(dir_part) + 1 + strlen(name) >= (unsigned)buf_sz)
        return false;

    sprintf(buf, "%s%s", dir_part, name);
    return true;
}
예제 #3
0
/**
 *  "txt" points to a "<?" sequence.
 *  We handle "<?program" and "<?auto-options" directives.
 *  All others are treated as comments.
 *
 *  @param[in,out] opts  program option descriptor
 *  @param[in]     txt   scanning pointer
 *  @returns       the next character to look at
 */
static char *
handle_directive(tOptions * opts, char * txt)
{
#   define DIRECTIVE_TABLE                      \
    _dt_(zCfgProg,     program_directive)       \
    _dt_(zCfgAO_Flags, aoflags_directive)

    typedef char * (directive_func_t)(tOptions *, char *);
#   define _dt_(_s, _fn) _fn,
    static directive_func_t * dir_disp[] = {
        DIRECTIVE_TABLE
    };
#   undef  _dt_

#   define _dt_(_s, _fn) 1 +
    static int  const   dir_ct  = DIRECTIVE_TABLE 0;
    static char const * dir_names[DIRECTIVE_TABLE 0];
#   undef _dt_

    int    ix;

    if (dir_names[0] == NULL) {
        ix = 0;
#   define _dt_(_s, _fn) dir_names[ix++] = _s;
        DIRECTIVE_TABLE;
#   undef _dt_
    }

    for (ix = 0; ix < dir_ct; ix++) {
        size_t len = strlen(dir_names[ix]);
        if (  (strncmp(txt + 2, dir_names[ix], len) == 0)
           && (! IS_VALUE_NAME_CHAR(txt[len+2])) )
            return dir_disp[ix](opts, txt + len + 2);
    }

    /*
     *  We don't know what this is.  Skip it.
     */
    txt = strchr(txt+2, '>');
    if (txt != NULL)
        txt++;
    return txt;
#   undef DIRECTIVE_TABLE
}
예제 #4
0
파일: defLex.c 프로젝트: pexip/os-autogen
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *
 *  It may be a number, a name, a keyword or garbage.
 *  Figure out which.
 */
static char*
assembleName(char * pzScan, te_dp_event * pRetVal)
{
    /*
     *  Check for a number.
     *  Scan it in and advance "pzScan".
     */
    if (  IS_DEC_DIGIT_CHAR(*pzScan)
       || (  (*pzScan == '-')
          && IS_DEC_DIGIT_CHAR(pzScan[1])
       )  )  {
        pz_token = pzScan;
        (void)strtol(pzScan, &pzScan, 0);
        *pRetVal = DP_EV_NUMBER;
        return pzScan;
    }

    if (! IS_UNQUOTABLE_CHAR(*pzScan))
        AG_ABEND(aprf("%s Error: Invalid input char '%c' in %s on line %d\n",
                      pzProg, *pzScan, pCurCtx->pzCtxFname, pCurCtx->lineNo));

    {
        unsigned char* pz = (unsigned char*)pzScan;

        while (IS_VALUE_NAME_CHAR(*pz))          pz++;

        if (IS_UNQUOTABLE_CHAR(*pz)) {
            *pRetVal = DP_EV_OTHER_NAME;
            while (IS_UNQUOTABLE_CHAR(*++pz))    ;
        } else
            *pRetVal = DP_EV_VAR_NAME;

        /*
         *  Return a NAME token, maybe.
         *  If the name is actually a keyword,
         *  we will return that token code instead.
         */
        pz_token = pzScan;
        pzScan   = (char*)pz;
    }

    /*
     *  Now scan the keyword table.
     */
    if (*pRetVal == DP_EV_VAR_NAME) {
        char sv_ch = *pzScan;  /* preserve the following character */
        int  kw_ix = 0;
        *pzScan = NUL;         /* NUL terminate the name           */

        do  {
            if (streqvcmp(apzKeywords[ kw_ix ], (char*)pz_token) == 0) {
                /*
                 *  Return the keyword token code instead of DP_EV_NAME
                 */
                *pRetVal = aKeywordTkn[ kw_ix ];
                break;
            }
        } while (++kw_ix < KEYWORD_CT);

        *pzScan = sv_ch;         /* restore the following character  */
    }

    return pzScan;
}
예제 #5
0
/*
 *  canonicalizeName:  remove white space and roughly verify the syntax.
 *  This procedure will consume everything from the source string that
 *  forms a valid AutoGen compound definition name.
 *  We leave legally when:
 *  1.  the state is "CN_NAME_ENDED", AND
 *  2.  We stumble into a character that is not either '[' or name_sep_ch
 *      (always skipping white space).
 *  We start in CN_START.
 */
LOCAL int
canonicalizeName(char* pzD, char const* pzS, int srcLen)
{
    typedef enum {
        CN_START_NAME = 0,   /* must find a name */
        CN_NAME_ENDED,       /* must find '[' or name_sep_ch or we end */
        CN_INDEX,            /* must find name, number, '$' or ']' */
        CN_INDEX_CLOSE,      /* must find ']' */
        CN_INDEX_ENDED       /* must find name_sep_ch or we end */
    } teConState;

    teConState state = CN_START_NAME;

    char const* pzOri = pzS;
    char*       pzDst = pzD;
    size_t      stLen = srcLen;

    /*
     *  Before anything, skip a leading name_sep_ch as a special hack
     *  to force a current context lookup.
     */
    pzS = SPN_WHITESPACE_CHARS(pzS);
    if (pzOri != pzS) {
        srcLen -= pzS - pzOri;
        if (srcLen <= 0)
            pzS = zNil;
    }

    if (*pzS == name_sep_ch) {
        *(pzD++) = name_sep_ch;
        pzS++;
        if (--srcLen <= 0)
            pzS = zNil;
    }

 nextSegment:

    /*
     *  The next segment may always start with an alpha character,
     *  but an index may also start with a number.  The full number
     *  validation will happen in find_by_index().
     */
    {
        char * p = SPN_WHITESPACE_CHARS(pzS);
        if (p != pzS) {
            srcLen -= p - pzS;
            if (srcLen <= 0)
                pzS = zNil;
            pzS = p;
        }
    }

    switch (state) {
    case CN_START_NAME:
        if (! IS_VAR_FIRST_CHAR(*pzS))
            return bad_def_name(pzDst, pzOri, stLen);
        state = CN_NAME_ENDED;  /* we found the start of our first name */
        break;  /* fall through to name/number consumption code */

    case CN_NAME_ENDED:
        switch (*pzS++) {
        case '[':
            *(pzD++) = '[';
            state = CN_INDEX;
            break;

        case '.': case '/':
            if (pzS[-1] == name_sep_ch) {
                *(pzD++) = name_sep_ch;
                state = CN_START_NAME;
                break;
            }

        default:
            /* legal exit -- we have a name already */
            *pzD = NUL;
            return srcLen;
        }

        if (--srcLen <= 0)
            return bad_def_name(pzDst, pzOri, stLen);
        goto nextSegment;

    case CN_INDEX:
        /*
         *  An index.  Valid syntaxes are:
         *
         *    '[' <#define-d name> ']'
         *    '[' <number> ']'
         *    '['  '$'  ']'
         *    '['       ']'
         *
         *  We will check for and handle the last case right here.
         *  The next cycle must find the index closer (']').
         */
        state = CN_INDEX_CLOSE;

        /*
         *  Numbers and #define-d names are handled at the end of the switch.
         *  '$' and ']' are handled immediately below.
         */
        if (IS_ALPHANUMERIC_CHAR(*pzS))
            break;

        /*
         *  A solitary '$' is the highest index, whatever that happens to be
         *  We process that right here because down below we only accept
         *  name-type characters and this is not VMS.
         */
        if (*pzS == '$') {
            if (--srcLen < 0)
                return bad_def_name(pzDst, pzOri, stLen);

            *(pzD++) = *(pzS++);
            goto nextSegment;
        }
        /* FALLTHROUGH */

    case CN_INDEX_CLOSE:
        /*
         *  Nothing else is okay.
         */
        if ((*(pzD++) = *(pzS++)) != ']')
            return bad_def_name(pzDst, pzOri, stLen);

        if (--srcLen <= 0) {
            *pzD = NUL;
            return srcLen;
        }
        state = CN_INDEX_ENDED;
        goto nextSegment;

    case CN_INDEX_ENDED:
        if ((*pzS != name_sep_ch) || (--srcLen < 0)) {
            *pzD = NUL;
            return srcLen;
        }
        *(pzD++) = *(pzS++);

        state = CN_START_NAME;
        goto nextSegment;
    }

    /*
     *  The next state must be either looking for what comes after the
     *  end of a name, or for the close bracket after an index.
     *  Whatever, the next token must be a name or a number.
     */
    assert((state == CN_NAME_ENDED) || (state == CN_INDEX_CLOSE));
    assert(IS_ALPHANUMERIC_CHAR(*pzS));

    /*
     *  Copy the name/number.  We already know the first character is valid.
     *  However, we must *NOT* downcase #define names...
     */
    while (IS_VALUE_NAME_CHAR(*pzS)) {
        char ch = *(pzS++);
        if ((state != CN_INDEX_CLOSE) && IS_UPPER_CASE_CHAR(ch))
            *(pzD++) = tolower(ch);

        else switch (ch) { /* force the separator chars to be '_' */
        case '-':
        case '^':
            *(pzD++) = '_';
            break;

        default:
            *(pzD++) = ch;
        }

        if (--srcLen <= 0) {
            pzS = zNil;
            break;
        }
    }

    goto nextSegment;
}
예제 #6
0
파일: configfile.c 프로젝트: pexip/os-ntp
/**
 *  "pzText" points to a '<' character, followed by an alpha.
 *  The end of the entry is either the "/>" following the name, or else a
 *  "</name>" string.
 */
static char *
handle_struct(tOptions * pOpts, tOptState * pOS, char * pzText, int dir)
{
    tOptionLoadMode mode = option_load_mode;
    tOptionValue    valu;

    char* pzName = ++pzText;
    char* pzData;
    char* pcNulPoint;

    while (IS_VALUE_NAME_CHAR(*pzText))  pzText++;
    pcNulPoint = pzText;
    valu.valType = OPARG_TYPE_STRING;

    switch (*pzText) {
    case ' ':
    case '\t':
        pzText = parseAttributes(pOpts, pzText, &mode, &valu);
        if (*pzText == '>')
            break;
        if (*pzText != '/')
            return NULL;
        /* FALLTHROUGH */

    case '/':
        if (pzText[1] != '>')
            return NULL;
        *pzText = NUL;
        pzText += 2;
        loadOptionLine(pOpts, pOS, pzName, dir, mode);
        return pzText;

    case '>':
        break;

    default:
        pzText = strchr(pzText, '>');
        if (pzText != NULL)
            pzText++;
        return pzText;
    }

    /*
     *  If we are here, we have a value.  "pzText" points to a closing angle
     *  bracket.  Separate the name from the value for a moment.
     */
    *pcNulPoint = NUL;
    pzData = ++pzText;

    /*
     *  Find the end of the option text and NUL terminate it
     */
    {
        char   z[64], *pz = z;
        size_t len = strlen(pzName) + 4;
        if (len > sizeof(z))
            pz = AGALOC(len, "scan name");

        sprintf(pz, "</%s>", pzName);
        *pzText = ' ';
        pzText = strstr(pzText, pz);
        if (pz != z) AGFREE(pz);

        if (pzText == NULL)
            return pzText;

        *pzText = NUL;

        pzText += len-1;
    }

    /*
     *  Rejoin the name and value for parsing by "loadOptionLine()".
     *  Erase any attributes parsed by "parseAttributes()".
     */
    memset(pcNulPoint, ' ', pzData - pcNulPoint);

    /*
     *  If we are getting a "string" value, the process the XML-ish
     *  %XX hex characters.
     */
    if (valu.valType == OPARG_TYPE_STRING) {
        char * pzSrc = pzData;
        char * pzDst = pzData;
        char bf[4];
        bf[2] = NUL;

        for (;;) {
            int ch = ((int)*(pzSrc++)) & 0xFF;
            switch (ch) {
            case NUL: goto string_fixup_done;

            case '%':
                bf[0] = *(pzSrc++);
                bf[1] = *(pzSrc++);
                if ((bf[0] == NUL) || (bf[1] == NUL))
                    goto string_fixup_done;
                ch = strtoul(bf, NULL, 16);
                /* FALLTHROUGH */

            default:
                *(pzDst++) = ch;
            }
        } string_fixup_done:;
        *pzDst = NUL;
    }

    /*
     *  "pzName" points to what looks like text for one option/configurable.
     *  It is NUL terminated.  Process it.
     */
    loadOptionLine(pOpts, pOS, pzName, dir, mode);

    return pzText;
}
예제 #7
0
파일: configfile.c 프로젝트: pexip/os-ntp
/**
 *  "pzText" points to the start of some value name.
 *  The end of the entry is the end of the line that is not preceded by
 *  a backslash escape character.  The string value is always processed
 *  in "cooked" mode.
 */
static char *
handle_cfg(tOptions * pOpts, tOptState * pOS, char * pzText, int dir)
{
    char* pzName = pzText++;
    char* pzEnd  = strchr(pzText, '\n');

    if (pzEnd == NULL)
        return pzText + strlen(pzText);

    while (IS_VALUE_NAME_CHAR(*pzText)) pzText++;
    while (IS_WHITESPACE_CHAR(*pzText)) pzText++;
    if (pzText > pzEnd) {
    name_only:
        *pzEnd++ = NUL;
        loadOptionLine(pOpts, pOS, pzName, dir, OPTION_LOAD_UNCOOKED);
        return pzEnd;
    }

    /*
     *  Either the first character after the name is a ':' or '=',
     *  or else we must have skipped over white space.  Anything else
     *  is an invalid format and we give up parsing the text.
     */
    if ((*pzText == '=') || (*pzText == ':')) {
        while (IS_WHITESPACE_CHAR(*++pzText))   ;
        if (pzText > pzEnd)
            goto name_only;
    } else if (! IS_WHITESPACE_CHAR(pzText[-1]))
        return NULL;

    /*
     *  IF the value is continued, remove the backslash escape and push "pzEnd"
     *  on to a newline *not* preceded by a backslash.
     */
    if (pzEnd[-1] == '\\') {
        char* pcD = pzEnd-1;
        char* pcS = pzEnd;

        for (;;) {
            char ch = *(pcS++);
            switch (ch) {
            case NUL:
                pcS = NULL;

            case '\n':
                *pcD = NUL;
                pzEnd = pcS;
                goto copy_done;

            case '\\':
                if (*pcS == '\n') {
                    ch = *(pcS++);
                }
                /* FALLTHROUGH */
            default:
                *(pcD++) = ch;
            }
        } copy_done:;

    } else {
        /*
         *  The newline was not preceded by a backslash.  NUL it out
         */
        *(pzEnd++) = NUL;
    }

    /*
     *  "pzName" points to what looks like text for one option/configurable.
     *  It is NUL terminated.  Process it.
     */
    loadOptionLine(pOpts, pOS, pzName, dir, OPTION_LOAD_UNCOOKED);

    return pzEnd;
}
예제 #8
0
/*  scanXmlEntry
 *
 *  We've found a '<' character.  We ignore this if it is a comment or a
 *  directive.  If it is something else, then whatever it is we are looking
 *  at is bogus.  Returning NULL stops processing.
 */
static char const*
scanXmlEntry( char const* pzName, tOptionValue* pRes )
{
    size_t nameLen = 1, valLen = 0;
    char const*   pzScan = ++pzName;
    char const*   pzVal;
    tOptionValue  valu;
    tOptionValue* pNewVal;
    tOptionLoadMode save_mode = option_load_mode;

    if (! IS_VAR_FIRST_CHAR(*pzName)) {
        switch (*pzName) {
        default:
            pzName = NULL;
            break;

        case '!':
            pzName = strstr( pzName, "-->" );
            if (pzName != NULL)
                pzName += 3;
            break;

        case '?':
            pzName = strchr( pzName, '>' );
            if (pzName != NULL)
                pzName++;
            break;
        }
        return pzName;
    }

    pzScan++;
    while (IS_VALUE_NAME_CHAR( (int)*pzScan ))  { pzScan++; nameLen++; }
    if (nameLen > 64)
        return NULL;
    valu.valType = OPARG_TYPE_STRING;

    switch (*pzScan) {
    case ' ':
    case '\t':
        pzScan = parseAttributes(NULL, (char *)(intptr_t)pzScan,
	    &option_load_mode, &valu );
        if (*pzScan == '>') {
            pzScan++;
            break;
        }

        if (*pzScan != '/') {
            option_load_mode = save_mode;
            return NULL;
        }
        /* FALLTHROUGH */

    case '/':
        if (*++pzScan != '>') {
            option_load_mode = save_mode;
            return NULL;
        }
        addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
        option_load_mode = save_mode;
        return pzScan+1;

    default:
        option_load_mode = save_mode;
        return NULL;

    case '>':
        pzScan++;
        break;
    }

    pzVal = pzScan;

    {
        char z[68];
        char* pzD = z;
        int  ct = nameLen;
        char const* pzS = pzName;

        *(pzD++) = '<';
        *(pzD++) = '/';

        do  {
            *(pzD++) = *(pzS++);
        } while (--ct > 0);
        *(pzD++) = '>';
        *pzD = NUL;

        pzScan = strstr( pzScan, z );
        if (pzScan == NULL) {
            option_load_mode = save_mode;
            return NULL;
        }
        valLen = (pzScan - pzVal);
        pzScan += nameLen + 3;
        while (IS_WHITESPACE_CHAR(*pzScan))  pzScan++;
    }

    switch (valu.valType) {
    case OPARG_TYPE_NONE:
        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
        break;

    case OPARG_TYPE_STRING:
        pNewVal = addStringValue(
            &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen);

        if (option_load_mode == OPTION_LOAD_KEEP)
            break;
        mungeString( pNewVal->v.strVal, option_load_mode );
        break;

    case OPARG_TYPE_BOOLEAN:
        addBoolValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
        break;

    case OPARG_TYPE_NUMERIC:
        addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
        break;

    case OPARG_TYPE_HIERARCHY:
    {
        char* pz = AGALOC( valLen+1, "hierarchical scan" );
        if (pz == NULL)
            break;
        memcpy( pz, pzVal, valLen );
        pz[valLen] = NUL;
        addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen );
        AGFREE(pz);
        break;
    }

    case OPARG_TYPE_ENUMERATION:
    case OPARG_TYPE_MEMBERSHIP:
    default:
        break;
    }

    option_load_mode = save_mode;
    return pzScan;
}
예제 #9
0
/*  scanNameEntry
 *
 *  We have an entry that starts with a name.  Find the end of it, cook it
 *  (if called for) and create the name/value association.
 */
static char const*
scanNameEntry(char const* pzName, tOptionValue* pRes)
{
    tOptionValue* pNV;
    char const * pzScan = pzName+1; /* we know first char is a name char */
    char const * pzVal;
    size_t       nameLen = 1;
    size_t       dataLen = 0;

    /*
     *  Scan over characters that name a value.  These names may not end
     *  with a colon, but they may contain colons.
     */
    while (IS_VALUE_NAME_CHAR(*pzScan))   { pzScan++; nameLen++; }
    if (pzScan[-1] == ':')                { pzScan--; nameLen--; }
    while (IS_HORIZ_WHITE_CHAR(*pzScan))    pzScan++;

re_switch:
    switch (*pzScan) {
    case '=':
    case ':':
        while (IS_HORIZ_WHITE_CHAR( (int)*++pzScan ))  ;
        if ((*pzScan == '=') || (*pzScan == ':'))
            goto default_char;
        goto re_switch;

    case '\n':
    case ',':
        pzScan++;
        /* FALLTHROUGH */

    case NUL:
        addStringValue(&(pRes->v.nestVal), pzName, nameLen, NULL, (size_t)0);
        break;

    case '"':
    case '\'':
        pzVal = pzScan;
        pzScan = scanQuotedString( pzScan );
        dataLen = pzScan - pzVal;
        pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal,
                              dataLen );
        if ((pNV != NULL) && (option_load_mode == OPTION_LOAD_COOKED))
            ao_string_cook( pNV->v.strVal, NULL );
        break;

    default:
    default_char:
        /*
         *  We have found some strange text value.  It ends with a newline
         *  or a comma.
         */
        pzVal = pzScan;
        for (;;) {
            char ch = *(pzScan++);
            switch (ch) {
            case NUL:
                pzScan--;
                dataLen = pzScan - pzVal;
                goto string_done;
                /* FALLTHROUGH */

            case '\n':
                if (   (pzScan > pzVal + 2)
                    && (pzScan[-2] == '\\')
                    && (pzScan[ 0] != NUL))
                    continue;
                /* FALLTHROUGH */

            case ',':
                dataLen = (pzScan - pzVal) - 1;
            string_done:
                pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
                                      pzVal, dataLen );
                if (pNV != NULL)
                    removeLineContinue( pNV->v.strVal );
                goto leave_scan_name;
            }
        }
        break;
    } leave_scan_name:;

    return pzScan;
}