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); } }
/*=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; }
/*=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; }
/** * 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; }
/** * 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; }
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; }
/** * 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(); }
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); } }
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; }
/* * 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; }
/** * 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; }
/** * 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; }
/*=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; }
/** * 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; }
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; }
/*************************************************** * 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; }
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; }
/* * 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; }
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; }
/*=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; }
/** * 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; }
/*=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; } }
/*=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 }
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); }
/*=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; }
/* * 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. */ }
/* * 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; }
/** * 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 }
/*=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); }
/* 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; }