Пример #1
0
static void
init_scm(void)
{
    last_scm_cmd = SCHEME_INIT_TEXT;

    {
        SCM ini_res = ag_scm_c_eval_string_from_file_line(
            SCHEME_INIT_TEXT, AG_TEXT_STRTABLE_FILE, SCHEME_INIT_TEXT_LINENO);
        AGDUPSTR(libguile_ver, scm2display(ini_res), "ini res");
    }

    {
        unsigned int maj, min, mic;
        switch (sscanf(libguile_ver, "%u.%u.%u", &maj, &min, &mic)) {
        case 2:
        case 3: break;
        default:
            AG_ABEND(aprf(GUILE_VERSION_BAD, libguile_ver));
            /* NOT_REACHED */
        }
        maj = min + (100 * maj);
        if ((GUILE_VERSION / 1000) != maj)
            AG_ABEND(aprf(GUILE_VERSION_WRONG, libguile_ver,
                          MK_STR(GUILE_VERSION)));
    }

    {
#       if GUILE_VERSION >= 200000
#         define SCHEME_INIT_DEBUG SCHEME_INIT_DEBUG_2_0
#       else
#         define SCHEME_INIT_DEBUG SCHEME_INIT_DEBUG_1_6
#       endif
        char * p = aprf(INIT_SCM_ERRS_FMT, SCHEME_INIT_DEBUG);
#       undef  SCHEME_INIT_DEBUG

        last_scm_cmd = p;
        ag_scm_c_eval_string_from_file_line(p, __FILE__, __LINE__);
        AGFREE(p);
    }
}
Пример #2
0
/*=export_func  optionTimeVal
 * private:
 *
 * what:  process an option with a time duration.
 * arg:   + tOptions * + opts + program options descriptor +
 * arg:   + tOptDesc * + od   + the descriptor for this arg +
 *
 * doc:
 *  Decipher a time duration value.
=*/
void
optionTimeVal(tOptions * opts, tOptDesc * od)
{
    time_t val;

    if (INQUERY_CALL(opts, od))
        return;

    val = parse_duration(od->optArg.argString);
    if (val == BAD_TIME) {
        fprintf(stderr, zNotDuration, opts->pzProgName, od->optArg.argString);
        if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
            (*(opts->pUsageProc))(opts, EXIT_FAILURE);
    }

    if (od->fOptState & OPTST_ALLOC_ARG) {
        AGFREE(od->optArg.argString);
        od->fOptState &= ~OPTST_ALLOC_ARG;
    }

    od->optArg.argInt = (long)val;
}
Пример #3
0
/*=export_func  optionTimeVal
 * private:
 *
 * what:  process an option with a time duration.
 * arg:   + tOptions* + pOpts    + program options descriptor +
 * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
 *
 * doc:
 *  Decipher a time duration value.
=*/
void
optionTimeVal(tOptions * pOpts, tOptDesc * pOD)
{
    time_t val;

    if ((pOD->fOptState & OPTST_RESET) != 0)
        return;

    val = parse_duration(pOD->optArg.argString);
    if (val == BAD_TIME) {
        fprintf(stderr, zNotDuration, pOpts->pzProgName, pOD->optArg.argString);
        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
            (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
    }

    if (pOD->fOptState & OPTST_ALLOC_ARG) {
        AGFREE(pOD->optArg.argString);
        pOD->fOptState &= ~OPTST_ALLOC_ARG;
    }

    pOD->optArg.argInt = (unsigned long)val;
}
Пример #4
0
/**
 *  handle AutoOpts mode flags
 */
static char *
aoflags_directive(tOptions * pOpts, char * pzText)
{
    char * pz = pzText;

    while (IS_WHITESPACE_CHAR(*++pz))  ;
    pzText = strchr(pz, '>');
    if (pzText != NULL) {

        size_t len  = pzText - pz;
        char * ftxt = AGALOC(len + 1, "aoflags");

        memcpy(ftxt, pz, len);
        ftxt[len] = NUL;
        set_usage_flags(pOpts, ftxt);
        AGFREE(ftxt);

        pzText++;
    }

    return pzText;
}
Пример #5
0
/**
 *  handle AutoOpts mode flags.
 *
 *  @param[in,out] opts  program option descriptor
 *  @param[in]     txt   scanning pointer
 *  @returns       the next character to look at
 */
static char *
aoflags_directive(tOptions * opts, char * txt)
{
    char * pz;

    pz = SPN_WHITESPACE_CHARS(txt+1);
    txt = strchr(pz, '>');
    if (txt != NULL) {

        size_t len  = (unsigned)(txt - pz);
        char * ftxt = AGALOC(len + 1, "aoflags");

        memcpy(ftxt, pz, len);
        ftxt[len] = NUL;
        set_usage_flags(opts, ftxt);
        AGFREE(ftxt);

        txt++;
    }

    return txt;
}
Пример #6
0
static void
printSetMemberArg(FILE * fp, tOptDesc * pOD)
{
    uintptr_t val = pOD->optArg.argEnum;

    /*
     *  This is a magic incantation that will convert the
     *  bit flag values back into a string suitable for printing.
     */
    (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD);
    printEntry( fp, pOD, (const void*)(pOD->optArg.argString));

    if (pOD->optArg.argString != NULL) {
        /*
         *  set membership strings get allocated
         */
        AGFREE( pOD->optArg.argString );
        pOD->fOptState &= ~OPTST_ALLOC_ARG;
    }

    pOD->optArg.argEnum = val;
}
Пример #7
0
/**
 *  This gets called when all is well at the end.
 */
LOCAL void
cleanup(tTemplate* pTF)
{
    if (HAVE_OPT(USED_DEFINES))
        print_used_defines();

    if (pfDepends != NULL)
        wrap_up_depends();

    optionFree(&autogenOptions);

    for (;;) {
        tTemplate* pT = pNamedTplList;
        if (pT == NULL)
            break;
        pNamedTplList = (tTemplate*)(void*)(pT->pNext);
        unloadTemplate(pT);
    }

    AGFREE(forInfo.fi_data);
    unloadTemplate(pTF);
    unloadDefs();
}
Пример #8
0
static void
print_one_paragraph(char const * text, bool plain, FILE * fp)
{
    if (plain) {
#ifdef ENABLE_NLS
#ifdef HAVE_LIBINTL_H
#ifdef DEBUG_ENABLED
#undef gettext
#endif
        char * buf = dgettext("libopts", text);
        if (buf == text)
            text = gettext(text);
#endif /* HAVE_LIBINTL_H */
#endif /* ENABLE_NLS */
        fputs(text, fp);
    }

    else {
        char const * t = optionQuoteString(text, LINE_SPLICE);
        fprintf(fp, PUTS_FMT, t);
        AGFREE((void *)t);
    }
}
Пример #9
0
Файл: rows.c Проект: 274914765/C
static int delete_data_entry (SCROLLER_T * scrlr, void *delete_me)
{
    NEXTED_PTR_T *data_ptr = delete_me;

    register NEXTED_PTR_T *tmp;

    if (data_ptr == scrlr->first_data_ptr)
    {
        scrlr->first_data_ptr = data_ptr->next;
        if (data_ptr == scrlr->last_data_ptr)
            scrlr->last_data_ptr = NULL;
    }
    else
    {                            /* not first */
        for (tmp = scrlr->first_data_ptr; tmp; tmp = tmp->next)
        {
            if (tmp->next == data_ptr)
            {
                if (data_ptr == scrlr->last_data_ptr)
                    scrlr->last_data_ptr = tmp;
                tmp->next = data_ptr->next;
                break;
            }
        }                        /* for */
    }                            /* not first */

    if (data_ptr == scrlr->current_data_ptr)
        scrlr->current_data_ptr = data_ptr->next;

    if (scrlr->data_destructor)
        scrlr->data_destructor (scrlr, data_ptr);
    AGFREE (data_ptr);
    scrlr->data_created--;
    scrlr->data_stored--;

    return 0;
}
Пример #10
0
/*
 *  eval_true - should a string be interpreted as TRUE?
 *
 *  It is always true unless:
 *
 *  1.  it is the empty string
 *  2.  it starts with a digit and the number evaluates to zero
 *  3.  it starts with either "#f" or "#F"
 *  4.  For its length or its first five characters (whichever is less)
 *      it matches the string "false"
 */
static ag_bool
eval_true(void)
{
    ag_bool needFree;
    ag_bool res = AG_TRUE;
    char const * pz = evalExpression(&needFree);

    if (IS_DEC_DIGIT_CHAR(*pz))
        res = (atoi(pz) == 0) ? AG_FALSE : AG_TRUE;

    else switch (*pz) {
    case NUL:
        res = AG_FALSE;
        break;

    case '#':
        if ((pz[1] == 'f') || (pz[1] == 'F'))
            res = AG_FALSE;
        break;

    case 'f':
    case 'F':
    {
        int len = strlen(pz);
        if (len > 5)
            len = 5;
        if (strneqvcmp(EVAL_TRUE_FALSE_STR, pz, len) == 0)
            res = AG_FALSE;
        break;
    }
    }

    if (needFree)
        AGFREE(pz);

    return res;
}
Пример #11
0
/**
 *  This directive @i{is} processed, but only if the expression begins with
 *  either a back quote (@code{`}) or an open parenthesis (@code{(}).
 *  Text within the back quotes are handed off to the shell for processing
 *  and parenthesized text is handed off to Guile.  Multiple line expressions
 *  must be joined with backslashes.
 *
 *  If the @code{shell-script} or @code{scheme-expr} do not yield @code{true}
 *  valued results, autogen will be aborted.  If @code{<anything else>} or
 *  nothing at all is provided, then this directive is ignored.
 *
 *  The result is @code{false} (and fails) if the result is empty, the
 *  number zero, or a string that starts with the letters 'n' or 'f' ("no"
 *  or "false").
 */
char *
doDir_assert(directive_enum_t id, char const * dir, char * scan_next)
{
    (void)id;
    dir = SPN_WHITESPACE_CHARS(dir);
    switch (*dir) {
    case '`':
    {
        char * pzS = (char *)dir+1;
        char * pzR = SPN_WHITESPACE_BACK(pzS, NULL);

        if (*(--pzR) != '`')
            break; /* not a valid script */

        *pzR = NUL;
        pzS = shell_cmd((char const *)pzS);
        check_assert_str(pzS, dir);
        AGFREE(pzS);
        break;
    }

    case '(':
    {
        SCM res = ag_scm_c_eval_string_from_file_line(
            dir, cctx->scx_fname, cctx->scx_line);

        check_assert_str(scm2display(res), dir);
        break;
    }

    default:
        break;
    }

    return scan_next;
}
Пример #12
0
/**
 * handle program segmentation of config file.
 *
 *  @param[in,out] opts  program option descriptor
 *  @param[in]     txt   scanning pointer
 *  @returns       the next character to look at
 */
static char *
program_directive(tOptions * opts, char * txt)
{
    static char const ttlfmt[] = "<?";
    size_t ttl_len  = sizeof(ttlfmt) + strlen(zCfgProg);
    char * ttl      = AGALOC(ttl_len, "prog title");
    size_t name_len = strlen(opts->pzProgName);

    memcpy(ttl, ttlfmt, sizeof(ttlfmt) - 1);
    memcpy(ttl + sizeof(ttlfmt) - 1, zCfgProg, ttl_len - (sizeof(ttlfmt) - 1));

    do  {
        txt = SPN_WHITESPACE_CHARS(txt+1);

        if (  (strneqvcmp(txt, opts->pzProgName, (int)name_len) == 0)
           && (IS_END_XML_TOKEN_CHAR(txt[name_len])) ) {
            txt += name_len;
            break;
        }

        txt = strstr(txt, ttl);
    } while (txt != NULL);

    AGFREE(ttl);
    if (txt != NULL)
        for (;;) {
            if (*txt == NUL) {
                txt = NULL;
                break;
            }
            if (*(txt++) == '>')
                break;
        }

    return txt;
}
Пример #13
0
/*=macfunc ESAC
 *
 *  what:   Terminate the @code{CASE} Template Block
 *  in-context:
 *
 *  desc:
 *    This macro ends the @code{CASE} function template block.
 *    For a complete description, @xref{CASE}.
=*/
tMacro*
mFunc_Case(tTemplate* pT, tMacro* pMac)
{
    typedef tSuccess (t_match_proc)(char const *, char const *);
    /*
     *  There are only 15 procedures because the case insenstive matching
     *  get mapped into the previous four.  The last three are "match always",
     *  "match if a value was found" "match if no value found".
     */
    static t_match_proc * const match_procs[] = {
        &Select_Compare_Full,
        &Select_Compare_End,
        &Select_Compare_Start,
        &Select_Compare,

        &Select_Equivalent_Full,
        &Select_Equivalent_End,
        &Select_Equivalent_Start,
        &Select_Equivalent,

        &Select_Match_Full,
        &Select_Match_End,
        &Select_Match_Start,
        &Select_Match,

        &Select_Match_Always,
        &Select_Match_Existence,
        &Select_Match_NonExistence
    };

    static char const * const match_names[] = {
        "COMPARE_FULL",
        "COMPARE_END",
        "COMPARE_START",
        "CONTAINS",

        "EQUIVALENT_FULL",
        "EQUIVALENT_END",
        "EQUIVALENT_START",
        "EQUIV_CONTAINS",

        "MATCH_FULL",
        "MATCH_END",
        "MATCH_START",
        "MATCH_WITHIN",

        "MATCH_ALWAYS",
        "MATCH_EXISTENCE",
        "MATCH_NONEXISTENCE"
    };

    tMacro*   pEnd = pT->aMacros + pMac->endIndex;
    ag_bool needFree;
    char const * pzSampleText = evalExpression(&needFree);

    /*
     *  Search through the selection clauses until we either
     *  reach the end of the list for this CASE macro, or we match.
     */
    for (;;) {
        tSuccess mRes;
        pMac = pT->aMacros + pMac->sibIndex;
        if (pMac >= pEnd) {
            if (OPT_VALUE_TRACE >= TRACE_BLOCK_MACROS) {
                fprintf(pfTrace, "CASE string `%s' did not match\n",
                        pzSampleText);

                if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
                    fprintf(pfTrace, zFileLine, pCurTemplate->pzTplFile,
                            pMac->lineNo);
            }

            break;
        }

        /*
         *  The current macro becomes the selected selection macro
         */
        pCurMacro = pMac;
        mRes = (*(match_procs[pMac->funcCode & 0x0F])
               )(pzSampleText, pT->pzTemplText + pMac->ozText);

        /*
         *  IF match, THEN generate and stop looking for a match.
         */
        if (SUCCEEDED(mRes)) {
            if (OPT_VALUE_TRACE >= TRACE_BLOCK_MACROS) {
                fprintf(pfTrace, "CASE string `%s' %s matched `%s'\n",
                        pzSampleText,
                        match_names[pMac->funcCode & 0x0F],
                        pT->pzTemplText + pMac->ozText);

                if (OPT_VALUE_TRACE == TRACE_EVERYTHING)
                    fprintf(pfTrace, zFileLine, pCurTemplate->pzTplFile,
                            pMac->lineNo);
            }

            generateBlock(pT, pMac + 1, pT->aMacros + pMac->sibIndex);
            break;
        }
        else if (OPT_VALUE_TRACE == TRACE_EVERYTHING) {
            fprintf(pfTrace, "CASE no match: `%s' %s vs. `%s'\n",
                    pzSampleText,
                    match_names[pMac->funcCode & 0x0F],
                    pT->pzTemplText + pMac->ozText);
        }
    }

    if (needFree)
        AGFREE((void*)pzSampleText);

    return pEnd;
}
Пример #14
0
/**
 *  Invokes @code{$SHELL} or @file{/bin/sh} on a script that should
 *  generate AutoGen definitions.  It does this using the same server
 *  process that handles the back-quoted @code{`} text.
 *  The block of text handed to the shell is terminated with
 *  the #endshell directive.
 *
 *  @strong{CAUTION}@:  let not your @code{$SHELL} be @code{csh}.
 */
char *
doDir_shell(directive_enum_t id, char const * arg, char * scan_next)
{
    static size_t const endshell_len = sizeof("\n#endshell") - 1;

    scan_ctx_t * pCtx;
    char *       pzText = scan_next;

    (void)arg;
    (void)id;

    /*
     *  The output time will always be the current time.
     *  The dynamic content is always current :)
     */
    maxfile_time = outfile_time = time(NULL);

    /*
     *  IF there are no data after the '#shell' directive,
     *  THEN we won't write any data
     *  ELSE we have to find the end of the data.
     */
    if (strncmp(pzText, DIRECT_SHELL_END_SHELL+1, endshell_len-1) == 0)
        return scan_next;

    {
        char * pz = strstr(scan_next, DIRECT_SHELL_END_SHELL);
        if (pz == NULL)
            AG_ABEND(aprf(DIRECT_SHELL_NOEND, cctx->scx_fname,
                          cctx->scx_line));

        while (scan_next < pz) {
            if (*(scan_next++) == NL) cctx->scx_line++;
        }

        *scan_next = NUL;
    }

    /*
     *  Advance the scan pointer to the next line after '#endshell'
     *  IF there is no such line,
     *  THEN the scan will resume on a zero-length string.
     */
    scan_next = strchr(scan_next + endshell_len, NL);
    if (scan_next == NULL)
        scan_next = VOIDP(zNil);

    /*
     *  Save the scan pointer into the current context
     */
    cctx->scx_scan  = scan_next;

    /*
     *  Run the shell command.  The output text becomes the
     *  "file text" that is used for more definitions.
     */
    pzText = shell_cmd(pzText);
    if (pzText == NULL)
        return scan_next;

    if (*pzText == NUL) {
        AGFREE(pzText);
        return scan_next;
    }

    /*
     *  Get the space for the output data and for context overhead.
     *  This is an extra allocation and copy, but easier than rewriting
     *  'loadData()' for this special context.
     */
    pCtx = (scan_ctx_t *)AGALOC(sizeof(scan_ctx_t) + strlen(pzText) + 4,
                             "shell output");

    /*
     *  Link the new scan data into the context stack
     */
    pCtx->scx_next = cctx;
    cctx           = pCtx;

    /*
     *  Set up the rest of the context structure
     */
    AGDUPSTR(pCtx->scx_fname, DIRECT_SHELL_COMP_DEFS, DIRECT_SHELL_COMP_DEFS);
    pCtx->scx_scan  =
    pCtx->scx_data  = (char *)(pCtx + 1);
    pCtx->scx_line  = 0;
    strcpy(pCtx->scx_scan, pzText);
    AGFREE(pzText);

    return pCtx->scx_scan;
}
Пример #15
0
static int
write_eventControl(int action, u_char * var_val, u_char var_val_type,
                   size_t var_val_len, u_char * statP,
                   oid * name, size_t name_len)
{
    long            long_temp;
    char           *char_temp;
    int             leaf_id, snmp_status;
    static int      prev_action = COMMIT;
    RMON_ENTRY_T   *hdr;
    CRTL_ENTRY_T   *cloned_body;

    switch (action) {
    case RESERVE1:
    case FREE:
    case UNDO:
    case ACTION:
    case COMMIT:
    default:
        return ROWAPI_do_another_action(name, eventEntryFirstIndexBegin,
                                        action, &prev_action,
                                        table_ptr, sizeof(CRTL_ENTRY_T));

    case RESERVE2:
        /*
         * get values from PDU, check them and save them in the cloned entry 
         */
        long_temp = name[eventEntryFirstIndexBegin];
        leaf_id = (int) name[eventEntryFirstIndexBegin - 1];
        hdr = ROWAPI_find(table_ptr, long_temp);        /* it MUST be OK */
        cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
        switch (leaf_id) {
        case Leaf_event_index:
            return SNMP_ERR_NOTWRITABLE;
        case Leaf_event_description:
            char_temp = AGMALLOC(1 + MAX_event_description);
            if (!char_temp)
                return SNMP_ERR_TOOBIG;
            snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
                                                  var_val_len,
                                                  MAX_event_description,
                                                  1, NULL, char_temp);
            if (SNMP_ERR_NOERROR != snmp_status) {
                AGFREE(char_temp);
                return snmp_status;
            }

            if (cloned_body->event_description)
                AGFREE(cloned_body->event_description);

            cloned_body->event_description = AGSTRDUP(char_temp);
            /*
             * ag_trace ("rx: event_description=<%s>", cloned_body->event_description); 
             */
            AGFREE(char_temp);

            break;
        case Leaf_event_type:
            snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
                                               var_val_len,
                                               EVENT_NONE,
                                               EVENT_LOG_AND_TRAP,
                                               &long_temp);
            if (SNMP_ERR_NOERROR != snmp_status) {
                return snmp_status;
            }
            cloned_body->event_type = long_temp;
            break;
        case Leaf_event_last_time_sent:
            return SNMP_ERR_NOTWRITABLE;
        case Leaf_event_community:
            char_temp = AGMALLOC(1 + MAX_event_community);
            if (!char_temp)
                return SNMP_ERR_TOOBIG;
            snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
                                                  var_val_len,
                                                  MAX_event_community,
                                                  1, NULL, char_temp);
            if (SNMP_ERR_NOERROR != snmp_status) {
                AGFREE(char_temp);
                return snmp_status;
            }

            if (cloned_body->event_community)
                AGFREE(cloned_body->event_community);

            cloned_body->event_community = AGSTRDUP(char_temp);
            AGFREE(char_temp);

            break;
        case Leaf_eventOwner:
            if (hdr->new_owner)
                AGFREE(hdr->new_owner);
            hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
            if (!hdr->new_owner)
                return SNMP_ERR_TOOBIG;
            snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
                                                  var_val_len,
                                                  MAX_OWNERSTRING,
                                                  1, NULL, hdr->new_owner);
            if (SNMP_ERR_NOERROR != snmp_status) {
                return snmp_status;
            }

            break;
        case Leaf_eventStatus:
            snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
                                               var_val_len,
                                               RMON1_ENTRY_VALID,
                                               RMON1_ENTRY_INVALID,
                                               &long_temp);
            if (SNMP_ERR_NOERROR != snmp_status) {
                return snmp_status;
            }
            hdr->new_status = long_temp;
            break;
        default:
            ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
                     (int) leaf_id);
            return SNMP_ERR_NOSUCHNAME;
        }                       /* of switch by 'leaf_id' */
        break;
    }                           /* of switch by actions */

    prev_action = action;
    return SNMP_ERR_NOERROR;
}
Пример #16
0
/***************************************************
 * Function:write_etherStatsEntry 
 ***************************************************/
static int
write_etherStatsEntry(int action, u_char * var_val, u_char var_val_type,
                      size_t var_val_len, u_char * statP,
                      oid * name, size_t name_len)
{
    long            long_temp;
    int             leaf_id, snmp_status;
    static int      prev_action = COMMIT;
    RMON_ENTRY_T   *hdr;
    CRTL_ENTRY_T   *cloned_body;
    CRTL_ENTRY_T   *body;

    switch (action) {
    case RESERVE1:
    case FREE:
    case UNDO:
    case ACTION:
    case COMMIT:
    default:
        snmp_status =
            ROWAPI_do_another_action(name, etherStatsEntryFirstIndexBegin,
                                     action, &prev_action, table_ptr,
                                     sizeof(CRTL_ENTRY_T));
        if (SNMP_ERR_NOERROR != snmp_status) {
            ag_trace("failed action %d with %d", action, snmp_status);
        }
        break;

    case RESERVE2:
        /*
         * get values from PDU, check them and save them in the cloned entry 
         */
        long_temp = name[etherStatsEntryFirstIndexBegin];
        leaf_id = (int) name[etherStatsEntryFirstIndexBegin - 1];
        hdr = ROWAPI_find(table_ptr, long_temp);        /* it MUST be OK */
        cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
        body = (CRTL_ENTRY_T *) hdr->body;
        switch (leaf_id) {
        case Leaf_etherStatsDataSource:
            snmp_status = AGUTIL_get_oid_value(var_val, var_val_type,
                                               var_val_len,
                                               &cloned_body->data_source);
            if (SNMP_ERR_NOERROR != snmp_status) {
                return snmp_status;
            }
            if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
                snmp_oid_compare(cloned_body->data_source.objid,
                                 cloned_body->data_source.length,
                                 body->data_source.objid,
                                 body->data_source.length))
                return SNMP_ERR_BADVALUE;
            break;

            break;
        case Leaf_etherStatsOwner:
            if (hdr->new_owner)
                AGFREE(hdr->new_owner);
            hdr->new_owner = AGMALLOC(MAX_OWNERSTRING);;
            if (!hdr->new_owner)
                return SNMP_ERR_TOOBIG;
            snmp_status = AGUTIL_get_string_value(var_val, var_val_type,
                                                  var_val_len,
                                                  MAX_OWNERSTRING,
                                                  1, NULL, hdr->new_owner);
            if (SNMP_ERR_NOERROR != snmp_status) {
                return snmp_status;
            }
            break;
        case Leaf_etherStatsStatus:
            snmp_status = AGUTIL_get_int_value(var_val, var_val_type,
                                               var_val_len,
                                               RMON1_ENTRY_VALID,
                                               RMON1_ENTRY_INVALID,
                                               &long_temp);
            if (SNMP_ERR_NOERROR != snmp_status) {
                ag_trace("cannot browse etherStatsStatus");
                return snmp_status;
            }
            hdr->new_status = long_temp;
            break;
            break;
        default:
            ag_trace("%s:unknown leaf_id=%d\n", table_ptr->name,
                     (int) leaf_id);
            return SNMP_ERR_NOSUCHNAME;
        }                       /* of switch by 'leaf_id' */
        break;
    }                           /* of switch by 'action' */

    prev_action = action;
    return SNMP_ERR_NOERROR;
}
Пример #17
0
int
ROWAPI_commit(TABLE_DEFINTION_T * table_ptr, u_long ctrl_index)
{
    register RMON_ENTRY_T *eptr;

    eptr = ROWAPI_find(table_ptr, ctrl_index);
    if (!eptr) {
        ag_trace("Smth wrong ?");
        return SNMP_ERR_GENERR;
    }

    eptr->only_just_created = 0;

    switch (eptr->new_status) { /* this status we want to set */
    case RMON1_ENTRY_CREATE_REQUEST:   /* copy tmp => eprt */
        if (eptr->new_owner) {
            if (eptr->owner)
                AGFREE(eptr->owner);
            eptr->owner = AGSTRDUP(eptr->new_owner);
        }

        if (table_ptr->ClbkCopy && eptr->tmp)
            table_ptr->ClbkCopy(eptr);
        break;
    case RMON1_ENTRY_INVALID:
        ROWAPI_delete_clone(table_ptr, ctrl_index);
        rowapi_delete(eptr);
#if 0                           /* for debug */
        dbg_f_AG_MEM_REPORT();
#endif
        break;
    case RMON1_ENTRY_VALID:    /* copy tmp => eprt and activate */
        /*
         * Our MIB understanding extension: we permit to set
         * VALID when entry doesn't exit, in this case PDU has to have
         * the nessessary & valid set of non-default values
         */
        if (eptr->new_owner) {
            if (eptr->owner)
                AGFREE(eptr->owner);
            eptr->owner = AGSTRDUP(eptr->new_owner);
        }
        if (table_ptr->ClbkCopy && eptr->tmp)
            table_ptr->ClbkCopy(eptr);
        if (RMON1_ENTRY_VALID != eptr->status) {
            rowapi_activate(table_ptr, eptr);
        }
        break;
    case RMON1_ENTRY_UNDER_CREATION:   /* deactivate (if need) and copy tmp => eprt */
        /*
         * Our MIB understanding extension: we permit to travel from
         * VALID to 'UNDER_CREATION' state
         */
        rowapi_deactivate(table_ptr, eptr);
        if (eptr->new_owner) {
            if (eptr->owner)
                AGFREE(eptr->owner);
            eptr->owner = AGSTRDUP(eptr->new_owner);
        }
        if (table_ptr->ClbkCopy && eptr->tmp)
            table_ptr->ClbkCopy(eptr);
        break;
    }

    ROWAPI_delete_clone(table_ptr, ctrl_index);
    return SNMP_ERR_NOERROR;
}
Пример #18
0
/*
 * creates an entry, locats it in proper sorted order by index
 * Row is initialized to zero,
 * except: 'next', 'table_ptr', 'index',
 * 'timer_id' & 'status'=(RMON1_ENTRY_UNDER_CREATION)
 * Calls (if need) ClbkCreate.
 * Schedules for timeout under entry creation (id of this
 * scheduling is saved in 'timer_id').
 * Returns 0: OK,
 -1:max. number exedes;
 -2:malloc failed;
 -3:ClbkCreate failed */
int
ROWAPI_new(TABLE_DEFINTION_T * table_ptr, u_long ctrl_index)
{
    register RMON_ENTRY_T *eptr;
    register RMON_ENTRY_T *prev = NULL;
    register RMON_ENTRY_T *enew;

    /*
     * check on 'max.number'
     */
    if (table_ptr->max_number_of_entries > 0 &&
            table_ptr->current_number_of_entries >=
            table_ptr->max_number_of_entries)
        return -1;

    /*
     * allocate memory for the header
     */
    enew = (RMON_ENTRY_T *) AGMALLOC(sizeof(RMON_ENTRY_T));
    if (!enew)
        return -2;

    /*
     * init the header
     */
    memset(enew, 0, sizeof(RMON_ENTRY_T));
    enew->ctrl_index = ctrl_index;
    enew->table_ptr = (void *) table_ptr;
    enew->status = RMON1_ENTRY_UNDER_CREATION;
    enew->only_just_created = 1;

    /*
     * create the body: alloc it and set defaults
     */
    if (table_ptr->ClbkCreate) {
        if (0 != table_ptr->ClbkCreate(enew)) {
            AGFREE(enew);
            return -3;
        }
    }

    table_ptr->current_number_of_entries++;

    /*
     * find the place : before 'eptr' and after 'prev'
     */
    for (eptr = table_ptr->first; eptr; eptr = eptr->next) {
        if (ctrl_index < eptr->ctrl_index)
            break;
        prev = eptr;
    }

    /*
     * insert it
     */
    enew->next = eptr;
    if (prev)
        prev->next = enew;
    else
        table_ptr->first = enew;

    enew->timer_id = snmp_alarm_register(MAX_CREATION_TIME, 0,
                                         rowapi_too_long_creation_callback,
                                         enew);
    ag_trace("Entry %ld in %s has been created",
             enew->ctrl_index, table_ptr->name);
    return 0;
}
Пример #19
0
static int
write_alarmEntry (int action, u_char * var_val, u_char var_val_type,
                  size_t var_val_len, u_char * statP, oid * name, size_t name_len)
{
    long long_tmp;

    int leaf_id, snmp_status;

    static int prev_action = COMMIT;

    RMON_ENTRY_T *hdr;

    CRTL_ENTRY_T *cloned_body;

    CRTL_ENTRY_T *body;

    switch (action)
    {
        case RESERVE1:
        case FREE:
        case UNDO:
        case ACTION:
        case COMMIT:
        default:
            return ROWAPI_do_another_action (name, alarmEntryFirstIndexBegin,
                                             action, &prev_action, table_ptr, sizeof (CRTL_ENTRY_T));
        case RESERVE2:
            /*
             * get values from PDU, check them and save them in the cloned entry 
             */
            long_tmp = name[alarmEntryFirstIndexBegin];
            leaf_id = (int) name[alarmEntryFirstIndexBegin - 1];
            hdr = ROWAPI_find (table_ptr, long_tmp);    /* it MUST be OK */
            cloned_body = (CRTL_ENTRY_T *) hdr->tmp;
            body = (CRTL_ENTRY_T *) hdr->body;
            switch (leaf_id)
            {
                case IDalarmInterval:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type, var_val_len, 0, MMM_MAX, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->interval = long_tmp;
                    break;
                case IDalarmVariable:
                    snmp_status = AGUTIL_get_oid_value (var_val, var_val_type, var_val_len, &cloned_body->var_name);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    if (RMON1_ENTRY_UNDER_CREATION != hdr->status &&
                        snmp_oid_compare (cloned_body->var_name.objid,
                                          cloned_body->var_name.length, body->var_name.objid, body->var_name.length))
                        return SNMP_ERR_BADVALUE;
                    break;

                    break;
                case IDalarmSampleType:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type,
                                                        var_val_len,
                                                        SAMPLE_TYPE_ABSOLUTE, SAMPLE_TYPE_DELTE, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->sample_type = long_tmp;
                    break;
                case IDalarmStartupAlarm:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type,
                                                        var_val_len, ALARM_RISING, ALARM_BOTH, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->startup_type = long_tmp;
                    break;
                case IDalarmRisingThreshold:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type, var_val_len, 0, MMM_MAX, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->rising_threshold = long_tmp;
                    break;
                case IDalarmFallingThreshold:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type, var_val_len, 0, 0xFFFFFFFFl, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->falling_threshold = long_tmp;
                    break;
                case IDalarmRisingEventIndex:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type, var_val_len, 0,    /* min. value */
                                                        0,    /* max. value */
                                                        &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->rising_event_index = long_tmp;
                    break;
                case IDalarmFallingEventIndex:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type, var_val_len, 0,    /* min. value */
                                                        0,    /* max. value */
                                                        &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    cloned_body->falling_event_index = long_tmp;
                    break;
                case IDalarmOwner:
                    if (hdr->new_owner)
                        AGFREE (hdr->new_owner);
                    hdr->new_owner = AGMALLOC (MAX_OWNERSTRING);;
                    if (!hdr->new_owner)
                        return SNMP_ERR_TOOBIG;
                    snmp_status = AGUTIL_get_string_value (var_val, var_val_type,
                                                           var_val_len, MAX_OWNERSTRING, 1, NULL, hdr->new_owner);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }

                    break;
                case IDalarmStatus:
                    snmp_status = AGUTIL_get_int_value (var_val, var_val_type,
                                                        var_val_len, RMON1_ENTRY_VALID, RMON1_ENTRY_INVALID, &long_tmp);
                    if (SNMP_ERR_NOERROR != snmp_status)
                    {
                        return snmp_status;
                    }
                    hdr->new_status = long_tmp;
                    break;
                default:
                    ag_trace ("%s:unknown leaf_id=%d\n", table_ptr->name, (int) leaf_id);
                    return SNMP_ERR_NOSUCHNAME;
            }                    /* of switch by 'leaf_id' */

            break;
    }                            /* of switch by actions */

    prev_action = action;
    return SNMP_ERR_NOERROR;
}
Пример #20
0
/*=export_func  optionNumericVal
 * private:
 *
 * what:  process an option with a numeric value.
 * arg:   + tOptions * + opts + program options descriptor +
 * arg:   + tOptDesc * + od   + the descriptor for this arg +
 *
 * doc:
 *  Decipher a numeric value.
=*/
void
optionNumericVal(tOptions * opts, tOptDesc * od)
{
    char * pz;
    long   val;

    /*
     *  Guard against all the different ways this procedure might get invoked
     *  when there is no string argument provided.
     */
    if (INQUERY_CALL(opts, od) || (od->optArg.argString == NULL))
        return;

    /*
     *  Numeric options may have a range associated with it.
     *  If it does, the usage procedure requests that it be
     *  emitted by passing a NULL od pointer.  Also bail out
     *  if there is no option argument or if we are being reset.
     */
    if (  (od == NULL)
            || (od->optArg.argString == NULL)
            || ((od->fOptState & OPTST_RESET) != 0)
            || (opts <= OPTPROC_EMIT_LIMIT))
        return;

    errno = 0;
    val = strtol(od->optArg.argString, &pz, 0);
    if ((pz == od->optArg.argString) || (errno != 0))
        goto bad_number;

    if ((od->fOptState & OPTST_SCALED_NUM) != 0)
        switch (*(pz++)) {
        case NUL:
            pz--;
            break;
        case 't':
            val *= 1000;
        case 'g':
            val *= 1000;
        case 'm':
            val *= 1000;
        case 'k':
            val *= 1000;
            break;

        case 'T':
            val *= 1024;
        case 'G':
            val *= 1024;
        case 'M':
            val *= 1024;
        case 'K':
            val *= 1024;
            break;

        default:
            goto bad_number;
        }

    if (*pz != NUL)
        goto bad_number;

    if (od->fOptState & OPTST_ALLOC_ARG) {
        AGFREE(od->optArg.argString);
        od->fOptState &= ~OPTST_ALLOC_ARG;
    }

    od->optArg.argInt = val;
    return;

bad_number:

    fprintf( stderr, zNotNumber, opts->pzProgName, od->optArg.argString );
    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
        (*(opts->pUsageProc))(opts, EXIT_FAILURE);

    errno = EINVAL;
    od->optArg.argInt = ~0;
}
Пример #21
0
/**
 *  Starting with the current directory, search the directory
 *  list trying to find the base template file name.
 */
LOCAL tSuccess
findFile(char const * pzFName,
         char * pzFullName,
         char const * const * papSuffixList,
         char const * pzReferrer)
{
    char * pzRoot;
    char * pzSfx;
    void * deallocAddr = NULL;

    tSuccess res = SUCCESS;

    /*
     *  Expand leading environment variables.
     *  We will not mess with embedded ones.
     */
    if (*pzFName == '$') {
        if (! optionMakePath(pzFullName, (int)AG_PATH_MAX, pzFName,
                             autogenOptions.pzProgPath))
            return FAILURE;

        AGDUPSTR(pzFName, pzFullName, "find file name");
        deallocAddr = (void*)pzFName;

        /*
         *  pzFName now points to the name the file system can use.
         *  It must _not_ point to pzFullName because we will likely
         *  rewrite that value using this pointer!
         */
    }

    /*
     *  Not a complete file name.  If there is not already
     *  a suffix for the file name, then append ".tpl".
     *  Check for immediate access once again.
     */
    pzRoot = strrchr(pzFName, '/');
    pzSfx  = (pzRoot != NULL)
             ? strchr(++pzRoot, '.')
             : strchr(pzFName,  '.');

    /*
     *  The referrer is useful only if it includes a directory name.
     */
    if (pzReferrer != NULL) {
        char * pz = strrchr(pzReferrer, '/');
        if (pz == NULL)
            pzReferrer = NULL;
        else {
            AGDUPSTR(pzReferrer, pzReferrer, "pzReferrer");
            pz = strrchr(pzReferrer, '/');
            *pz = NUL;
        }
    }

    /*
     *  IF the file name does not contain a directory separator,
     *  then we will use the TEMPL_DIR search list to keep hunting.
     */
    {
        static char const curdir[]  = ".";
        static char const zDirFmt[] = "%s/%s";

        /*
         *  Search each directory in our directory search list
         *  for the file.  We always force one copy of this option.
         */
        int  ct = STACKCT_OPT(TEMPL_DIRS);
        char const ** ppzDir = STACKLST_OPT(TEMPL_DIRS) + ct - 1;
        char const *  pzDir  = curdir;

        if (*pzFName == '/')
            ct = 0;

        do  {
            char * pzEnd;
            void * coerce;

            /*
             *  IF one of our template paths starts with '$', then expand it.
             */
            if (*pzDir == '$') {
                if (! optionMakePath(pzFullName, (int)AG_PATH_MAX, pzDir,
                                     autogenOptions.pzProgPath)) {
                    coerce = (void *)pzDir;
                    strcpy(coerce, curdir);

                } else {
                    AGDUPSTR(pzDir, pzFullName, "find directory name");
                    coerce = (void *)ppzDir[1];
                    free(coerce);
                    ppzDir[1] = pzDir; /* save the computed name for later */
                }
            }

            if ((*pzFName == '/') || (pzDir == curdir)) {
                size_t nln = strlen(pzFName);
                if (nln >= AG_PATH_MAX - MAX_SUFFIX_LEN)
                    break;

                memcpy(pzFullName, pzFName, nln);
                pzEnd  = pzFullName + nln;
                *pzEnd = NUL;
            }
            else {
                pzEnd = pzFullName
                    + snprintf(pzFullName, AG_PATH_MAX - MAX_SUFFIX_LEN,
                               zDirFmt, pzDir, pzFName);
            }

            if (read_okay(pzFullName))
                goto findFileReturn;

            /*
             *  IF the file does not already have a suffix,
             *  THEN try the ones that are okay for this file.
             */
            if ((pzSfx == NULL) && (papSuffixList != NULL)) {
                char const * const * papSL = papSuffixList;
                *(pzEnd++) = '.';

                do  {
                    strcpy(pzEnd, *(papSL++)); /* must fit */
                    if (read_okay(pzFullName))
                        goto findFileReturn;

                } while (*papSL != NULL);
            }

            if (*pzFName == '/')
                break;

            /*
             *  IF there is a referrer, use it before the rest of the
             *  TEMPL_DIRS We detect first time through by *both* pzDir value
             *  and ct value.  "ct" will have this same value next time
             *  through and occasionally "pzDir" will be set to "curdir", but
             *  never again when ct is STACKCT_OPT(TEMPL_DIRS)
             */
            if (  (pzReferrer != NULL)
               && (pzDir == curdir)
               && (ct == STACKCT_OPT(TEMPL_DIRS))) {

                pzDir = pzReferrer;
                ct++;

            } else {
                pzDir = *(ppzDir--);
            }
        } while (--ct >= 0);
    }

    res = FAILURE;

 findFileReturn:
    AGFREE(deallocAddr);
    AGFREE(pzReferrer);
    return res;
}
Пример #22
0
/*=export_func  optionUnstackArg
 * private:
 *
 * what:  Remove option args from a stack
 * arg:   + tOptions* + opts + program options descriptor +
 * arg:   + tOptDesc* + od   + the descriptor for this arg +
 *
 * doc:
 *  Invoked for options that are equivalenced to stacked options.
=*/
void
optionUnstackArg(tOptions * opts, tOptDesc * od)
{
    tArgList * arg_list;

    if (INQUERY_CALL(opts, od))
        return;

    arg_list = (tArgList*)od->optCookie;

    /*
     *  IF we don't have any stacked options,
     *  THEN indicate that we don't have any of these options
     */
    if (arg_list == NULL) {
        od->fOptState &= OPTST_PERSISTENT_MASK;
        if ((od->fOptState & OPTST_INITENABLED) == 0)
            od->fOptState |= OPTST_DISABLED;
        return;
    }

#ifdef WITH_LIBREGEX
    {
        regex_t   re;
        int       i, ct, dIdx;

        if (regcomp(&re, od->optArg.argString, REG_NOSUB) != 0)
            return;

        /*
         *  search the list for the entry(s) to remove.  Entries that
         *  are removed are *not* copied into the result.  The source
         *  index is incremented every time.  The destination only when
         *  we are keeping a define.
         */
        for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) {
            char const * pzSrc = arg_list->apzArgs[ i ];
            char *       pzEq  = strchr(pzSrc, '=');
            int          res;


            if (pzEq != NULL)
                *pzEq = NUL;

            res = regexec(&re, pzSrc, (size_t)0, NULL, 0);
            switch (res) {
            case 0:
                /*
                 *  Remove this entry by reducing the in-use count
                 *  and *not* putting the string pointer back into
                 *  the list.
                 */
                AGFREE(pzSrc);
                arg_list->useCt--;
                break;

            default:
            case REG_NOMATCH:
                if (pzEq != NULL)
                    *pzEq = '=';

                /*
                 *  IF we have dropped an entry
                 *  THEN we have to move the current one.
                 */
                if (dIdx != i)
                    arg_list->apzArgs[ dIdx ] = pzSrc;
                dIdx++;
            }
        }

        regfree(&re);
    }
#else  /* not WITH_LIBREGEX */
    {
        int i, ct, dIdx;

        /*
         *  search the list for the entry(s) to remove.  Entries that
         *  are removed are *not* copied into the result.  The source
         *  index is incremented every time.  The destination only when
         *  we are keeping a define.
         */
        for (i = 0, dIdx = 0, ct = arg_list->useCt; --ct >= 0; i++) {
            const char * pzSrc = arg_list->apzArgs[ i ];
            char *       pzEq  = strchr(pzSrc, '=');

            if (pzEq != NULL)
                *pzEq = NUL;

            if (strcmp(pzSrc, od->optArg.argString) == 0) {
                /*
                 *  Remove this entry by reducing the in-use count
                 *  and *not* putting the string pointer back into
                 *  the list.
                 */
                AGFREE(pzSrc);
                arg_list->useCt--;
            } else {
                if (pzEq != NULL)
                    *pzEq = '=';

                /*
                 *  IF we have dropped an entry
                 *  THEN we have to move the current one.
                 */
                if (dIdx != i)
                    arg_list->apzArgs[ dIdx ] = pzSrc;
                dIdx++;
            }
        }
    }
#endif /* WITH_LIBREGEX */
    /*
     *  IF we have unstacked everything,
     *  THEN indicate that we don't have any of these options
     */
    if (arg_list->useCt == 0) {
        od->fOptState &= OPTST_PERSISTENT_MASK;
        if ((od->fOptState & OPTST_INITENABLED) == 0)
            od->fOptState |= OPTST_DISABLED;
        AGFREE((void *)arg_list);
        od->optCookie = NULL;
    }
}
Пример #23
0
/*=export_func  optionPagedUsage
 * private:
 *
 * what:  emit help text and pass through a pager program.
 * arg:   + tOptions * + opts + program options descriptor +
 * arg:   + tOptDesc * + od   + the descriptor for this arg +
 *
 * doc:
 *  Run the usage output through a pager.
 *  This is very handy if it is very long.
 *  This is disabled on platforms without a working fork() function.
=*/
void
optionPagedUsage(tOptions * opts, tOptDesc * od)
{
#if ! defined(HAVE_WORKING_FORK)
    if ((od->fOptState & OPTST_RESET) != 0)
        return;

    (*opts->pUsageProc)(opts, EXIT_SUCCESS);
#else
    static bool sv_print_exit = false;
    static char * fil_name = NULL;

    /*
     *  IF we are being called after the usage proc is done
     *     (and thus has called "exit(2)")
     *  THEN invoke the pager to page through the usage file we created.
     */
    switch (pagerState) {
    case PAGER_STATE_INITIAL:
    {
        if ((od->fOptState & OPTST_RESET) != 0)
            return;
        option_usage_fp = open_tmp_usage(&fil_name);
        if (option_usage_fp == NULL)
            (*opts->pUsageProc)(opts, EXIT_SUCCESS);

        pagerState    = PAGER_STATE_READY;
        sv_print_exit = print_exit;

        /*
         *  Set up so this routine gets called during the exit logic
         */
        atexit((void(*)(void))optionPagedUsage);

        /*
         *  The usage procedure will now put the usage information into
         *  the temporary file we created above.  Keep any shell commands
         *  out of the result.
         */
        print_exit = false;
        (*opts->pUsageProc)(opts, EXIT_SUCCESS);

        /* NOTREACHED */
        _exit(EXIT_FAILURE);
    }

    case PAGER_STATE_READY:
        fil_name = mk_pager_cmd(fil_name);

        if (sv_print_exit) {
            fputs("\nexit 0\n", stdout);
            fclose(stdout);
            dup2(STDERR_FILENO, STDOUT_FILENO);

        } else {
            fclose(stderr);
            dup2(STDOUT_FILENO, STDERR_FILENO);
        }

        ignore_val( system( fil_name));
        AGFREE(fil_name);

    case PAGER_STATE_CHILD:
        /*
         *  This is a child process used in creating shell script usage.
         */
        break;
    }
#endif
}
Пример #24
0
LOCAL void
processTemplate(tTemplate* pTF)
{
    forInfo.fi_depth = 0;

    /*
     *  IF the template file does not specify any output suffixes,
     *  THEN we will generate to standard out with the suffix set to zNoSfx.
     *  With output going to stdout, we don't try to remove output on errors.
     */
    if (pOutSpecList == NULL) {
        do_stdout_tpl(pTF);
        return;
    }

    do  {
        tOutSpec*  pOS    = pOutSpecList;

        /*
         * We cannot be in Scheme processing.  We've either just started
         * or we've made a long jump from our own code.  If we've made a
         * long jump, we've printed a message that is sufficient and we
         * don't need to print any scheme expressions.
         */
        pzLastScheme = NULL;

        /*
         *  HOW was that we got here?
         */
        switch (setjmp(fileAbort)) {
        case SUCCESS:
            if (OPT_VALUE_TRACE >= TRACE_EVERYTHING) {
                fprintf(pfTrace, PROC_TPL_START, pOS->zSuffix);
                fflush(pfTrace);
            }
            /*
             *  Set the output file name buffer.
             *  It may get switched inside open_output.
             */
            open_output(pOS);
            memcpy(&fpRoot, pCurFp, sizeof(fpRoot));
            AGFREE(pCurFp);
            pCurFp         = &fpRoot;
            pzCurSfx       = pOS->zSuffix;
            currDefCtx     = rootDefCtx;
            pCurFp->flags &= ~FPF_FREE;
            pCurFp->pPrev  = NULL;
            generateBlock(pTF, pTF->aMacros, pTF->aMacros + pTF->macroCt);

            do  {
                out_close(AG_FALSE);  /* keep output */
            } while (pCurFp->pPrev != NULL);
            break;

        case PROBLEM:
            /*
             *  We got here by a long jump.  Close/purge the open files.
             */
            do  {
                out_close(AG_TRUE);  /* discard output */
            } while (pCurFp->pPrev != NULL);
            pzLastScheme = NULL; /* "problem" means "drop current output". */
            break;

        default:
            fprintf(pfTrace, PROC_TPL_BOGUS_RET, pzOopsPrefix);
            pzOopsPrefix = zNil;
            /* FALLTHROUGH */

        case FAILURE:
            /*
             *  We got here by a long jump.  Close/purge the open files.
             */
            do  {
                out_close(AG_TRUE);  /* discard output */
            } while (pCurFp->pPrev != NULL);

            /*
             *  On failure (or unknown jump type), we quit the program, too.
             */
            procState = PROC_STATE_ABORTING;
            do pOS = nextOutSpec(pOS);
            while (pOS != NULL);
            exit(EXIT_FAILURE);
        }

        pOutSpecList = nextOutSpec(pOS);
    } while (pOutSpecList != NULL);
}
Пример #25
0
/*=export_func  optionParseShell
 * private:
 *
 * what:  Decipher a boolean value
 * arg:   + tOptions * + pOpts    + program options descriptor +
 *
 * doc:
 *  Emit a shell script that will parse the command line options.
=*/
void
optionParseShell(tOptions * opts)
{
    /*
     *  Check for our SHELL option now.
     *  IF the output file contains the "#!" magic marker,
     *  it will override anything we do here.
     */
    if (HAVE_GENSHELL_OPT(SHELL))
        shell_prog = GENSHELL_OPT_ARG(SHELL);

    else if (! ENABLED_GENSHELL_OPT(SHELL))
        shell_prog = NULL;

    else if ((shell_prog = getenv("SHELL")),
             shell_prog == NULL)

        shell_prog = POSIX_SHELL;

    /*
     *  Check for a specified output file
     */
    if (HAVE_GENSHELL_OPT(SCRIPT))
        open_out(GENSHELL_OPT_ARG(SCRIPT), opts->pzProgName);
    
    emit_usage(opts);
    emit_setup(opts);

    /*
     *  There are four modes of option processing.
     */
    switch (opts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
    case OPTPROC_LONGOPT:
        fputs(LOOP_STR,         stdout);

        fputs(LONG_OPT_MARK,    stdout);
        fputs(INIT_LOPT_STR,    stdout);
        emit_long(opts);
        printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
        fputs(END_OPT_SEL_STR,  stdout);

        fputs(NOT_FOUND_STR,    stdout);
        break;

    case 0:
        fputs(ONLY_OPTS_LOOP,   stdout);
        fputs(INIT_LOPT_STR,    stdout);
        emit_long(opts);
        printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
        break;

    case OPTPROC_SHORTOPT:
        fputs(LOOP_STR,         stdout);

        fputs(FLAG_OPT_MARK,    stdout);
        fputs(INIT_OPT_STR,     stdout);
        emit_flag(opts);
        printf(OPT_ARG_FMT,     opts->pzPROGNAME);
        fputs(END_OPT_SEL_STR,  stdout);

        fputs(NOT_FOUND_STR,    stdout);
        break;

    case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
        fputs(LOOP_STR,         stdout);

        fputs(LONG_OPT_MARK,    stdout);
        fputs(INIT_LOPT_STR,    stdout);
        emit_long(opts);
        printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
        fputs(END_OPT_SEL_STR,  stdout);

        fputs(FLAG_OPT_MARK,    stdout);
        fputs(INIT_OPT_STR,     stdout);
        emit_flag(opts);
        printf(OPT_ARG_FMT,     opts->pzPROGNAME);
        fputs(END_OPT_SEL_STR,  stdout);

        fputs(NOT_FOUND_STR,    stdout);
        break;
    }

    emit_wrapup(opts);
    if ((script_trailer != NULL) && (*script_trailer != NUL))
        fputs(script_trailer, stdout);
    else if (ENABLED_GENSHELL_OPT(SHELL))
        printf(SHOW_PROG_ENV, opts->pzPROGNAME);

#ifdef HAVE_FCHMOD
    fchmod(STDOUT_FILENO, 0755);
#endif
    fclose(stdout);

    if (ferror(stdout))
        fserr_exit(opts->pzProgName, zwriting, zstdout_name);

    AGFREE(script_text);
    script_leader    = NULL;
    script_trailer   = NULL;
    script_text      = NULL;
}
Пример #26
0
/*
 *  process a single scheme expression, yielding text that gets processed
 *  into AutoGen definitions.
 */
static void
alist_to_autogen_def(void)
{
    static char const zSchemeText[] = "Scheme Computed Definitions";
    static char const zWrap[] = "(alist->autogen-def %s)";

    char*  pzText  = ++(pCurCtx->pzScan);
    char*  pzEnd   = (char*)skipScheme(pzText, pzText + strlen(pzText));

    SCM    res;
    size_t res_len;
    tScanCtx*  pCtx;

    /*
     *  Wrap the scheme expression with the `alist->autogen-def' function
     */
    {
        char endCh = *pzEnd;
        *pzEnd = NUL;
        pzText = aprf(zWrap, pzText);
        *pzEnd = endCh;
    }

    /*
     *  Run the scheme expression.  The result is autogen definition text.
     */
    procState = PROC_STATE_GUILE_PRELOAD;
    res = ag_scm_c_eval_string_from_file_line(
        pzText, pCurCtx->pzCtxFname, pCurCtx->lineNo );

    /*
     *  The result *must* be a string, or we choke.
     */
    if (! AG_SCM_STRING_P(res)) {
        static char const zEr[] =
            "Scheme definition expression does not yield string:\n";
        AG_ABEND(zEr);
    }

    res_len   = AG_SCM_STRLEN(res);
    procState = PROC_STATE_LOAD_DEFS;
    pCurCtx->pzScan = pzEnd;
    AGFREE(pzText);

    /*
     *  Now, push the resulting string onto the input stack
     *  and link the new scan data into the context stack
     */
    pCtx = (tScanCtx*)AGALOC(sizeof(tScanCtx) + 4 + res_len, "lex scan ctx");
    pCtx->pCtx  = pCurCtx;
    pCurCtx     = pCtx;

    /*
     *  Set up the rest of the context structure
     */
    AGDUPSTR(pCtx->pzCtxFname, zSchemeText, "scheme text");
    pCtx->pzScan = \
    pCtx->pzData = (char*)(pCtx+1);
    pCtx->lineNo = 0;
    memcpy((void*)(pCtx->pzScan), (void*)AG_SCM_CHARS(res), res_len);
    pCtx->pzScan[ res_len ] = NUL;

    /*
     *  At this point, the next token will be obtained
     *  from the newly allocated context structure.
     *  When empty, input will resume from the '}' that we
     *  left as the next input token in the old context.
     */
}
Пример #27
0
/*
 *  handle_opt
 *
 *  This routine handles equivalencing, sets the option state flags and
 *  invokes the handler procedure, if any.
 */
LOCAL tSuccess
handle_opt(tOptions* pOpts, tOptState* pOptState)
{
    /*
     *  Save a copy of the option procedure pointer.
     *  If this is an equivalence class option, we still want this proc.
     */
    tOptDesc* pOD = pOptState->pOD;
    tOptProc* pOP = pOD->pOptProc;
    if (pOD->fOptState & OPTST_ALLOC_ARG)
        AGFREE(pOD->optArg.argString);

    pOD->optArg.argString = pOptState->pzOptArg;

    /*
     *  IF we are presetting options, then we will ignore any un-presettable
     *  options.  They are the ones either marked as such.
     */
    if (  ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
       && ((pOD->fOptState & OPTST_NO_INIT) != 0)
       )
        return PROBLEM;

    /*
     *  IF this is an equivalence class option,
     *  THEN
     *      Save the option value that got us to this option
     *      entry.  (It may not be pOD->optChar[0], if this is an
     *      equivalence entry.)
     *      set the pointer to the equivalence class base
     */
    if (pOD->optEquivIndex != NO_EQUIVALENT) {
        tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;

        /*
         * IF the current option state has not been defined (set on the
         *    command line), THEN we will allow continued resetting of
         *    the value.  Once "defined", then it must not change.
         */
        if ((pOD->fOptState & OPTST_DEFINED) != 0) {
            /*
             *  The equivalenced-to option has been found on the command
             *  line before.  Make sure new occurrences are the same type.
             *
             *  IF this option has been previously equivalenced and
             *     it was not the same equivalenced-to option,
             *  THEN we have a usage problem.
             */
            if (p->optActualIndex != pOD->optIndex) {
                fprintf(stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
                        (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
                return FAILURE;
            }
        } else {
            /*
             *  Set the equivalenced-to actual option index to no-equivalent
             *  so that we set all the entries below.  This option may either
             *  never have been selected before, or else it was selected by
             *  some sort of "presetting" mechanism.
             */
            p->optActualIndex = NO_EQUIVALENT;
        }

        if (p->optActualIndex != pOD->optIndex) {
            /*
             *  First time through, copy over the state
             *  and add in the equivalence flag
             */
            p->optActualValue = pOD->optValue;
            p->optActualIndex = pOD->optIndex;
            pOptState->flags |= OPTST_EQUIVALENCE;
        }

        /*
         *  Copy the most recent option argument.  set membership state
         *  is kept in ``p->optCookie''.  Do not overwrite.
         */
        p->optArg.argString = pOD->optArg.argString;
        pOD = p;

    } else {
        pOD->optActualValue = pOD->optValue;
        pOD->optActualIndex = pOD->optIndex;
    }

    pOD->fOptState &= OPTST_PERSISTENT_MASK;
    pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT_MASK);

    /*
     *  Keep track of count only for DEFINED (command line) options.
     *  IF we have too many, build up an error message and bail.
     */
    if (  (pOD->fOptState & OPTST_DEFINED)
       && (++pOD->optOccCt > pOD->optMaxCt)  )  {

        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
            char const * pzEqv =
                (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;

            fputs(zErrOnly, stderr);

            if (pOD->optMaxCt > 1)
                fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv);
            else
                fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv);
        }

        return FAILURE;
    }

    /*
     *  If provided a procedure to call, call it
     */
    if (pOP != NULL)
        (*pOP)(pOpts, pOD);

    return SUCCESS;
}
Пример #28
0
/**
 *  The purpose of this function is to assign "long usage", short usage
 *  and version information to a shell variable.  Rather than wind our
 *  way through all the logic necessary to emit the text directly, we
 *  fork(), have our child process emit the text the normal way and
 *  capture the output in the parent process.
 *
 * @param[in] opts  the program options
 * @param[in] which what to print: long usage, usage or version
 * @param[in] od    for TT_VERSION, it is the version option
 */
static void
text_to_var(tOptions * opts, teTextTo which, tOptDesc * od)
{
#   define _TT_(n) static char const z ## n [] = #n;
    TEXTTO_TABLE
#   undef _TT_
#   define _TT_(n) z ## n ,
      static char const * ttnames[] = { TEXTTO_TABLE };
#   undef _TT_

#if ! defined(HAVE_WORKING_FORK)
    printf(SET_NO_TEXT_FMT, opts->pzPROGNAME, ttnames[which]);
#else
    int  fdpair[2];

    fflush(stdout);
    fflush(stderr);

    if (pipe(fdpair) != 0)
        fserr_exit(opts->pzProgName, "pipe", zinter_proc_pipe);

    switch (fork()) {
    case -1:
        fserr_exit(opts->pzProgName, "fork", opts->pzProgName);
        /* NOTREACHED */

    case 0:
        /*
         * Send both stderr and stdout to the pipe.  No matter which
         * descriptor is used, we capture the output on the read end.
         */
        dup2(fdpair[1], STDERR_FILENO);
        dup2(fdpair[1], STDOUT_FILENO);
        close(fdpair[0]);

        switch (which) {
        case TT_LONGUSAGE:
            (*(opts->pUsageProc))(opts, EXIT_SUCCESS);
            /* NOTREACHED */

        case TT_USAGE:
            (*(opts->pUsageProc))(opts, EXIT_FAILURE);
            /* NOTREACHED */

        case TT_VERSION:
            if (od->fOptState & OPTST_ALLOC_ARG) {
                AGFREE(od->optArg.argString);
                od->fOptState &= ~OPTST_ALLOC_ARG;
            }
            od->optArg.argString = "c";
            optionPrintVersion(opts, od);
            /* NOTREACHED */

        default:
            option_exits(EXIT_FAILURE);
            /* NOTREACHED */
        }
        /* NOTREACHED */

    default:
        close(fdpair[1]);
    }

    emit_var_text(opts->pzPROGNAME, ttnames[which], fdpair[0]);
#endif
}
Пример #29
0
/*=export_func  optionPrintParagraphs
 * private:
 *
 * what:  Print a paragraph of usage text
 * arg:   + char const * + text  + a block of text that has bee i18n-ed +
 * arg:   + bool         + plain + false -> wrap text in fputs()        +
 * arg:   + FILE *       + fp    + the stream file pointer for output   +
 *
 * doc:
 *  This procedure is called in two contexts: when a full or short usage text
 *  has been provided for display, and when autogen is assembling a list of
 *  translatable texts in the optmain.tlib template.  In the former case, \a
 *  plain is set to \a true, otherwise \a false.
 *
 *  Anything less than 256 characters in size is printed as a single unit.
 *  Otherwise, paragraphs are detected.  A paragraph break is defined as just
 *  before a non-empty line preceded by two newlines or a line that starts
 *  with at least one space character but fewer than 8 space characters.
 *  Lines indented with tabs or more than 7 spaces are considered continuation
 *  lines.
 *
 *  If 'plain' is true, we are emitting text for a user to see.  So, if it is
 *  true and NLS is not enabled, then just write the whole thing at once.
=*/
void
optionPrintParagraphs(char const * text, bool plain, FILE * fp)
{
    size_t len = strlen(text);
    char * buf;
#ifndef ENABLE_NLS
    if (plain || (len < 256))
#else
    if (len < 256)
#endif
    {
        print_one_paragraph(text, plain, fp);
        return;
    }

    AGDUPSTR(buf, text, "ppara");
    text = buf;

    for (;;) {
        char * scan;

        if (len < 256) {
        done:
            print_one_paragraph(buf, plain, fp);
            break;
        }
        scan = buf;

    try_longer:
        scan = strchr(scan, NL);
        if (scan == NULL)
            goto done;

        if ((scan - buf) < 8) {
            scan++;
            goto try_longer;
        }

        scan++;
        if ((! isspace((int)*scan)) || (*scan == HT))
            /*
             * line starts with tab or non-whitespace --> continuation
             */
            goto try_longer;

        if (*scan == NL) {
            /*
             * Double newline -> paragraph break
             * Include all newlines in current paragraph.
             */
            while (*++scan == NL)  /*continue*/;

        } else {
            char * p = scan;
            int   sp_ct = 0;

            while (*p == ' ') {
                if (++sp_ct >= 8) {
                    /*
                     * Too many spaces --> continuation line
                     */
                    scan = p;
                    goto try_longer;
                }
                p++;
            }
        }

        /*
         * "scan" points to the first character of a paragraph or the
         * terminating NUL byte.
         */
        {
            char svch = *scan;
            *scan = NUL;
            print_one_paragraph(buf, plain, fp);
            len -= scan - buf;
            if (len <= 0)
                break;
            *scan = svch;
            buf = scan;
        }
    }
    AGFREE((void *)text);
}
Пример #30
0
/*  handleStructure
 *
 *  "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*
handleStructure(
    tOptions*     pOpts,
    tOptState*    pOS,
    char*         pzText,
    int           direction )
{
    tOptionLoadMode mode = option_load_mode;
    tOptionValue     valu;

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

    while (ISNAMECHAR( *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, direction, 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);

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

    return pzText;
}