/* **************************************************************************** * * paBuiltinRemove */ int paBuiltinRemove(char* name) { PaiArgument* aP; /* 1. lookup aP->option or aP->variable */ /* 2. if found - mark the aP as PaRemoved */ /* 3. Then paConfig needs the actions to do it */ paIterateInit(); while ((aP = paIterateNext(NULL)) != NULL) { char envVarName[128]; paEnvName(aP, envVarName, sizeof(envVarName)); if (((aP->option) && (strcmp(name, aP->option) == 0)) || ((aP->envName) && (strcmp(name, envVarName) == 0))) { aP->removed = true; break; } } if (aP == NULL) { char w[512]; snprintf(w, sizeof(w), "cannot remove builtin '%s' - not found", name); PA_WARNING(PasBuiltinRemove, w); return 1; } return 0; }
/* **************************************************************************** * * paValueFrom - */ PaFrom paValueFrom(char* oName) { PaiArgument* aP; paIterateInit(); while ((aP = paIterateNext(paiList)) != NULL) { char envVarName[64]; if (aP->option == NULL) { continue; } paEnvName(aP, envVarName, sizeof(envVarName)); if (aP->option && (strcmp(oName, aP->option) == 0)) { return aP->from; } else if (aP->envName && (strcmp(oName, envVarName) == 0)) { return aP->from; } } return PafError; }
/* **************************************************************************** * * envNameDuplicated - */ static bool envNameDuplicated(char* name, int start) { int ix; int opts = paOptionsNoOf(paiList); int matches = 0; if (name == NULL) { return false; } if (name[0] == 0) { return false; } for (ix = start; ix < opts; ix++) { PaiArgument* aP; char envVarName[128]; if ((aP = paIxLookup(paiList, ix)) == NULL) { break; } if (aP->removed == true) { continue; } if (aP->envName == NULL) { continue; } paEnvName(aP, envVarName, sizeof(envVarName)); if (strcmp(name, envVarName) == 0) { ++matches; } } if (matches <= 1) { return false; } return true; }
/* **************************************************************************** * * paFrom - from where did the value come? */ char* paFrom(PaiArgument* paList, const char* name) { PaiArgument* aP; paIterateInit(); while ((aP = paIterateNext(paList)) != NULL) { char envVarName[128]; paEnvName(aP, envVarName, sizeof(envVarName)); if ((aP->option) && strcmp(aP->option, name) == 0) { break; } if ((aP->envName) && strcmp(envVarName, name) == 0) { break; } } if (aP->type == PaLastArg) { return (char*) "unrecognized option"; } switch (aP->from) { case PafError: return (char*) "error"; case PafUnchanged: return (char*) "not altered"; case PafDefault: return (char*) "default value"; case PafEnvVar: return (char*) "environment variable"; case PafRcFile: return (char*) "RC file"; case PafArgument: return (char*) "command line argument"; } return (char*) "origin unknown"; }
/* **************************************************************************** * * paRcFileParse - parse startup file */ int paRcFileParse(void) { char dir[1024]; char path[1024]; char line[512]; int lineNo = 0; FILE* fP; char w[512]; LM_ENTRY(); if ((paRcFileName == NULL) || (paRcFileName[0] == 0)) { LM_EXIT(); return 0; } if (dirFind(dir, sizeof(dir)) == 0) { LM_T(LmtPaRcFile, ("RC file '%s' found in directory '%s'", paRcFileName, dir)); } else { return 0; } snprintf(path, sizeof(path), "%s/%s", dir, paRcFileName); if ((fP = fopen(path, "r")) == NULL) { LM_RE(-1, ("error opening RC file '%s': %s", path, strerror(errno))); } LM_T(LmtPaRcFile, ("parsing RC file %s", path)); while (fgets(line, sizeof(line), fP) != NULL) { char* delim; char* var; char* val; PaiArgument* aP; bool varFound; char envVarName[128]; ++lineNo; LM_T(LmtPaRcFile, ("got line %d", lineNo)); newlineStrip(line); LM_T(LmtPaRcFile, ("got line %d", lineNo)); commentStrip(line, '#'); LM_T(LmtPaRcFile, ("got line %d", lineNo)); baWsStrip(line); LM_T(LmtPaRcFile, ("got line %d", lineNo)); if (line[0] == 0) { continue; } LM_T(LmtPaRcFile, ("got line %d", lineNo)); delim = strchr(line, '='); if (delim == NULL) { char w[512]; snprintf(w, sizeof(w), "%s[%d]: no delimiter found", path, lineNo); PA_WARNING(PasParseError, w); continue; } *delim = 0; var = line; val = &delim[1]; baWsStrip(var); baWsStrip(val); if (var[0] == 0) { fclose(fP); LM_RE(-1, ("%s[%d]: no variable ...", path, lineNo)); } if (val[0] == 0) { fclose(fP); LM_RE(-1, ("%s[%d]: no value for variable %s", path, lineNo, var)); } varFound = false; paIterateInit(); while ((aP = paIterateNext(paiList)) != NULL) { paEnvName(aP, envVarName, sizeof(envVarName)); if (strcmp(var, envVarName) == 0) { aP->from = PafRcFile; LM_T(LmtPaRcFileVal, ("got value '%s' for %s", val, envVarName)); varFound = true; break; } } if (varFound == false) { char w[512]; snprintf(w, sizeof(w), "%s[%d]: variable '%s' not recognized", path, lineNo, var); PA_WARNING(PasNoSuchVariable, w); continue; } switch (aP->type) { case PaString: strcpy((char*) aP->varP, val); break; case PaBoolean: if ((strcmp(val, "TRUE") == 0) || (strcmp(val, "ON") == 0) || (strcmp(val, "yes") == 0) || (strcmp(val, "1") == 0)) *((bool*) (int64_t) aP->varP) = true; else if ((strcmp(val, "FALSE") == 0) || (strcmp(val, "OFF") == 0) || (strcmp(val, "no") == 0) || (strcmp(val, "0") == 0)) *((bool*) (int64_t) aP->varP) = false; else { snprintf(w, sizeof(w), "bad value '%s' for boolean variable %s", val, envVarName); PA_WARNING(PasNoSuchBooleanValue, w); } break; case PaSList: case PaIList: LM_TODO(("lists ...")); break; case PaInt: case PaIntU: *((int64_t*) aP->varP) = baStoi(val); break; case PaShort: case PaShortU: *((int16_t*) (int64_t) aP->varP) = baStoi(val); break; case PaFloat: *((float*) (int64_t) aP->varP) = baStof(val); break; case PaDouble: *((double*) (int64_t) aP->varP) = baStod(val); break; case PaChar: case PaCharU: *((char*) (int64_t) aP->varP) = baStoi(val); break; default: snprintf(w, sizeof(w), "bad type %d for variable %s", aP->type, envVarName); PA_WARNING(PasNoSuchType, w); } } fclose(fP); return 0; }
/* **************************************************************************** * * paArgInit - */ static int paArgInit(PaArgument* paList) { PaiArgument* aP; int parNo = 0; int ix = 0; int args = 0; while (paList[ix].type != PaLastArg) { ++args; ++ix; } paiList = (PaiArgument*) calloc(args + 1, sizeof(PaiArgument)); if (paiList == NULL) { PA_E(("Error allocating room for %d options", args)); exit(1); } PA_M(("Allocated room for %d args (plus one)", args)); for (ix = 0; ix < args + 1; ix++) { PA_M(("Copying arg %d", ix)); memcpy(&paiList[ix], &paList[ix], sizeof(paList[ix])); paiList[ix].isBuiltin = false; } paIterateInit(); while ((aP = paIterateNext(paiList)) != NULL) { char envVarName[128]; /* Set argument to be unused */ aP->used = 0; aP->hasDefault = true; aP->hasMinLimit = true; aP->hasMaxLimit = true; aP->aux = 0; /* Set the value to come from nowhere */ aP->from = PafUnchanged; if ((aP->option != NULL) && (aP->option[0] == 0)) { aP->option = NULL; } if ((aP->envName != NULL) && (aP->envName[0] == 0)) { aP->envName = NULL; } if ((aP->envName != NULL) && ((aP->envName[0] == ' ') || (aP->envName[0] == '\t'))) { char w[512]; snprintf(w, sizeof(w), "%s", "found an item with var name starting with whitespace - forbidden"); PA_WARNING(PasVarNameWs, w); continue; } /* Set the name of the argument */ if (aP->option == NULL) { if (aP->envName == NULL) { snprintf(aP->name, sizeof(aP->name), "parameter %d", ++parNo); aP->what = PawParameter; } else { char envVarName[128]; snprintf(aP->name, sizeof(aP->name), "variable/parameter %s", paEnvName(aP, envVarName, sizeof(envVarName))); aP->what = PawVariable; } } else if ((aP->option[0] == ' ') && (aP->option[1] == 0)) { ++parNo; if (aP->envName == NULL) { snprintf(aP->name, sizeof(aP->name), "parameter %d", parNo); aP->what = PawParameter; } else { char envVarName[128]; snprintf(aP->name, sizeof(aP->name), "parameter %s", paEnvName(aP, envVarName, sizeof(envVarName))); aP->what = PawVariable | PawParameter; } } else { if (aP->envName == NULL) { snprintf(aP->name, sizeof(aP->name), "option '%s'", aP->option); aP->what = PawOption; } else { snprintf(aP->name, sizeof(aP->name), "option '%s'", aP->option); aP->what = PawOption | PawVariable; } } if (optionNameDuplicated((char*) aP->option, ix) == true) { char w[512]; snprintf(w, sizeof(w), "%s (%s) duplicated in source code", aP->name, aP->description); PA_WARNING(PasOptionNameDuplicated, w); aP->removed = true; } paEnvName(aP, envVarName, sizeof(envVarName)); if (envNameDuplicated(envVarName, ix) == true) { char w[512]; snprintf(w, sizeof(w), "Env var '%s' (%s) duplicated in source code", envVarName, aP->description); PA_WARNING(PasEnvNameDuplicated, w); aP->removed = true; } ++ix; } return 0; }
/* **************************************************************************** * * paExtendedUsage - print extended synopsis */ void paExtendedUsage(void) { char* spacePad; char string[80]; PaiArgument* aP; int optNameMaxLen = 0; int varNameMaxLen = 0; int valsMaxLen = 0; char format[64]; char progNAME[128]; bool firstLine = true; snprintf(progNAME, sizeof(progNAME), "Extended Usage: %s ", progName); spacePad = (char*) strdup(progNAME); memset(spacePad, 0x20202020, strlen(spacePad)); /* replace progNAME */ PA_M(("-------------- Preparing list for Extended usage -----------------")); paIterateInit(); while ((aP = paIterateNext(paiList)) != NULL) { char name[128]; char vals[128]; char defVal[20]; char minVal[20]; char maxVal[20]; char realVal[80]; char out[256]; char out2[256]; PA_M(("processing '%s' for extended usage\n", aP->name)); /* 1. Option Name */ memset(name, 0, sizeof(name)); if (PA_IS_OPTION(aP) && (aP->sort == PaOpt)) { snprintf(name, sizeof(name), "[%s]", paFullName(aP, string, sizeof(string))); } else if (PA_IS_OPTION(aP) && (aP->sort == PaReq)) { snprintf(name, sizeof(name), "%s", paFullName(aP, string, sizeof(string))); } else if (PA_IS_PARAMETER(aP) && (aP->sort == PaOpt)) { snprintf(name, sizeof(name), "(%s)", aP->description); } else if (PA_IS_PARAMETER(aP) && (aP->sort == PaReq)) { snprintf(name, sizeof(name), "[%s]", aP->description); } optNameMaxLen = MAX(strlen(name), (unsigned int) optNameMaxLen); /* 2. Variable Name */ memset(name, 0, sizeof(name)); if (PA_IS_VARIABLE(aP)) { paEnvName(aP, name, sizeof(name)); varNameMaxLen = MAX(strlen(name), (unsigned int) varNameMaxLen); } /* 3. Values */ getApVals(aP, defVal, sizeof(defVal), minVal, sizeof(minVal), maxVal, sizeof(maxVal), realVal, sizeof(realVal)); if (aP->hasDefault == false) { snprintf(name, sizeof(name), "%s", realVal); } else { snprintf(name, sizeof(name), "%s /%s/", realVal, defVal); } if ((aP->hasMinLimit == false) && (aP->hasMaxLimit == false)) { snprintf(vals, sizeof(vals), "%s", name); } else if (aP->hasMinLimit == false) { snprintf(vals, sizeof(vals), "%s <= %s", name, escape(out, maxVal)); } else if (aP->hasMaxLimit == false) { snprintf(vals, sizeof(vals), "%s >= %s", name, escape(out, minVal)); } else { snprintf(vals, sizeof(vals), "%s <= %s <= %s", escape(out, minVal), name, escape(out2, maxVal)); } valsMaxLen = MAX(strlen(vals), (unsigned int) valsMaxLen); } snprintf(format, sizeof(format), "%%-%ds %%-%ds %%-%ds %%-%ds %%s\n", (int) strlen(progName) + 1, optNameMaxLen + 2, varNameMaxLen + 2, valsMaxLen + 2); // paLogOn = true; paIterateInit(); while ((aP = paIterateNext(paiList)) != NULL) { char optName[128]; char varName[128]; char vals[128]; char from[128]; char defVal[20]; char minVal[20]; char maxVal[20]; char realVal[80]; char s[512]; if (aP->sort == PaHid) { PA_M(("skipping hidden option '%s'", aP->option)); continue; } /* 1. Option Name */ if (PA_IS_OPTION(aP) && (aP->sort == PaOpt)) { snprintf(optName, sizeof(optName), "[%s]", paFullName(aP, string, sizeof(string))); } else if (PA_IS_OPTION(aP) && (aP->sort == PaReq)) { snprintf(optName, sizeof(optName), "%s", paFullName(aP, string, sizeof(string))); } else if (PA_IS_PARAMETER(aP) && (aP->sort == PaOpt)) { snprintf(optName, sizeof(optName), "(%s)", aP->description); } else if (PA_IS_PARAMETER(aP) && (aP->sort == PaReq)) { snprintf(optName, sizeof(optName), "[%s]", aP->description); } else { snprintf(optName, sizeof(optName), " "); } /* 2. variable name */ if (PA_IS_VARIABLE(aP)) { paEnvName(aP, varName, sizeof(varName)); } else { snprintf(varName, sizeof(varName), " "); } /* 3. Limits */ if ((aP->type != PaSList) && (aP->type != PaIList)) { char valWithDef[128]; char fromN[64]; getApVals(aP, defVal, sizeof(defVal), minVal, sizeof(minVal), maxVal, sizeof(maxVal), realVal, sizeof(realVal)); if (aP->hasDefault == false) { snprintf(valWithDef, sizeof(valWithDef), "%s", realVal); } else { snprintf(valWithDef, sizeof(valWithDef), "%s /%s/", realVal, defVal); } if ((aP->hasMinLimit == false) && (aP->hasMaxLimit == false)) { snprintf(vals, sizeof(vals), "%s", valWithDef); } else if (aP->hasMinLimit == false) { snprintf(vals, sizeof(vals), "%s <= %s", valWithDef, maxVal); } else if (aP->hasMaxLimit == false) { snprintf(vals, sizeof(vals), "%s >= %s", valWithDef, minVal); } else { snprintf(vals, sizeof(vals), "%s <= %s <= %s", minVal, valWithDef, maxVal); } snprintf(from, sizeof(from), " (%s)", paFromName(aP, fromN, sizeof(fromN))); } else { snprintf(vals, sizeof(vals), " "); snprintf(from, sizeof(from), " "); } snprintf(s, sizeof(s), format, (firstLine)? progNAME : spacePad, optName, varName, vals, from); strncat(paResultString, s, sizeof(paResultString) - 1); firstLine = false; } // paLogOn = false; strncat(paResultString, "\r", sizeof(paResultString) - 1); free(spacePad); printf("%s\n", paResultString); exit(1); }