only update settings from args after verified as valid

This commit is contained in:
John
2022-09-24 15:44:56 +02:00
parent 406e7be6ef
commit 1f742a6235
3 changed files with 93 additions and 66 deletions
+5 -2
View File
@@ -84,6 +84,7 @@ static vector<string>* g_integrationVars = nullptr; //!< the integration settin
*/
static error_t knx_parse_opt(int key, char *arg, struct argp_state *state) {
result_t result;
unsigned int value;
switch (key) {
case O_URL: // --knxurl=[multicast][@interface]
if (arg == nullptr) { // empty is allowed
@@ -98,11 +99,12 @@ static error_t knx_parse_opt(int key, char *arg, struct argp_state *state) {
argp_error(state, "invalid knxrage value");
return EINVAL;
}
g_maxReadAge = parseInt(arg, 10, 0, 99999999, &result);
value = parseInt(arg, 10, 0, 99999999, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid knxrage");
return EINVAL;
}
g_maxReadAge = value;
break;
case O_AGW: // --knxwage=5
@@ -110,11 +112,12 @@ static error_t knx_parse_opt(int key, char *arg, struct argp_state *state) {
argp_error(state, "invalid knxwage value");
return EINVAL;
}
g_maxWriteAge = parseInt(arg, 10, 0, 99999999, &result);
value = parseInt(arg, 10, 0, 99999999, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid knxwage");
return EINVAL;
}
g_maxWriteAge = value;
break;
case O_INT: // --knxint=/etc/ebusd/knx.cfg
+70 -48
View File
@@ -340,23 +340,25 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
s_configPath = arg;
break;
case 's': // --scanconfig[=ADDR] (ADDR=<empty>|full|<hexaddr>)
opt->scanConfig = true;
if (opt->pollInterval == 0) {
argp_error(state, "scanconfig without polling may lead to invalid files included for certain products!");
return EINVAL;
}
opt->scanConfig = true;
if (!arg || arg[0] == 0 || strcmp("none", arg) == 0) {
opt->initialScan = ESC;
} else if (strcmp("full", arg) == 0) {
opt->initialScan = SYN;
} else {
opt->initialScan = (symbol_t)parseInt(arg, 16, 0x00, 0xff, &result);
if (result != RESULT_OK || !isValidAddress(opt->initialScan)) {
symbol_t address = (symbol_t)parseInt(arg, 16, 0x00, 0xff, &result);
if (result != RESULT_OK || !isValidAddress(address)) {
argp_error(state, "invalid initial scan address");
return EINVAL;
}
if (isMaster(opt->initialScan)) {
opt->initialScan = getSlaveAddress(opt->initialScan);
if (isMaster(address)) {
opt->initialScan = getSlaveAddress(address);
} else {
opt->initialScan = address;
}
}
if (opt->readOnly && opt->initialScan != ESC) {
@@ -379,11 +381,11 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
argp_error(state, "invalid checkconfig");
return EINVAL;
}
opt->dumpConfig = OF_DEFINITION;
if (!arg || arg[0] == 0 || strcmp("csv", arg) == 0) {
// no further flags
opt->dumpConfig = OF_DEFINITION;
} else if (strcmp("json", arg) == 0) {
opt->dumpConfig |= OF_NAMES | OF_UNITS | OF_COMMENTS | OF_VALUENAME | OF_ALL_ATTRS | OF_JSON;
opt->dumpConfig = OF_DEFINITION | OF_NAMES | OF_UNITS | OF_COMMENTS | OF_VALUENAME | OF_ALL_ATTRS | OF_JSON;
} else {
argp_error(state, "invalid dumpconfig");
return EINVAL;
@@ -398,15 +400,16 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->dumpConfigTo = arg;
break;
case O_POLINT: // --pollinterval=5
opt->pollInterval = parseInt(arg, 10, 0, 3600, &result);
value = parseInt(arg, 10, 0, 3600, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid pollinterval");
return EINVAL;
}
if (opt->pollInterval == 0 && opt->scanConfig) {
if (value == 0 && opt->scanConfig) {
argp_error(state, "scanconfig without polling may lead to invalid files included for certain products!");
return EINVAL;
}
opt->pollInterval = value;
break;
case 'i': // --inject[=stop]
if (opt->injectMessages || opt->checkConfig) {
@@ -425,12 +428,15 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
// eBUS options:
case 'a': // --address=31
opt->address = (symbol_t)parseInt(arg, 16, 0, 0xff, &result);
if (result != RESULT_OK || !isMaster(opt->address)) {
{
symbol_t address = (symbol_t)parseInt(arg, 16, 0, 0xff, &result);
if (result != RESULT_OK || !isMaster(address)) {
argp_error(state, "invalid address");
return EINVAL;
}
opt->address = address;
break;
}
case O_ANSWER: // --answer
if (opt->readOnly) {
argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
@@ -447,18 +453,20 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->acquireTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
break;
case O_ACQRET: // --acquireretries=3
opt->acquireRetries = parseInt(arg, 10, 0, 10, &result);
value = parseInt(arg, 10, 0, 10, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid acquireretries");
return EINVAL;
}
opt->acquireRetries = value;
break;
case O_SNDRET: // --sendretries=2
opt->sendRetries = parseInt(arg, 10, 0, 10, &result);
value = parseInt(arg, 10, 0, 10, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid sendretries");
return EINVAL;
}
opt->sendRetries = value;
break;
case O_RCVTIM: // --receivetimeout=25
value = parseInt(arg, 10, 1, 100000, &result); // backwards compatible (micros)
@@ -469,11 +477,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->receiveTimeout = value > 1000 ? value/1000 : value; // backwards compatible (micros)
break;
case O_MASCNT: // --numbermasters=0
opt->masterCount = parseInt(arg, 10, 0, 25, &result);
value = parseInt(arg, 10, 0, 25, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid numbermasters");
return EINVAL;
}
opt->masterCount = value;
break;
case O_GENSYN: // --generatesyn
if (opt->readOnly) {
@@ -515,21 +524,23 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->pidFile = arg;
break;
case 'p': // --port=8888
opt->port = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
value = parseInt(arg, 10, 1, 65535, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid port");
return EINVAL;
}
opt->port = (uint16_t)value;
break;
case O_LOCAL: // --localhost
opt->localOnly = true;
break;
case O_HTTPPT: // --httpport=0
opt->httpPort = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
value = parseInt(arg, 10, 1, 65535, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid httpport");
return EINVAL;
}
opt->httpPort = (uint16_t)value;
break;
case O_HTMLPA: // --htmlpath=/var/ebusd/html
if (arg == nullptr || arg[0] == 0 || strcmp("/", arg) == 0) {
@@ -562,37 +573,38 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->logFile = arg;
break;
case O_LOG: // --log=area(s):level
{
char* pos = strchr(arg, ':');
{
char* pos = strchr(arg, ':');
if (pos == nullptr) {
pos = strchr(arg, ' ');
if (pos == nullptr) {
pos = strchr(arg, ' ');
if (pos == nullptr) {
argp_error(state, "invalid log");
return EINVAL;
}
}
*pos = 0;
int facilities = parseLogFacilities(arg);
if (facilities == -1) {
argp_error(state, "invalid log: areas");
argp_error(state, "invalid log");
return EINVAL;
}
LogLevel level = parseLogLevel(pos + 1);
if (level == ll_COUNT) {
argp_error(state, "invalid log: level");
return EINVAL;
}
if (opt->logAreas != -1 || opt->logLevel != ll_COUNT) {
argp_error(state, "invalid log (combined with logareas or loglevel)");
return EINVAL;
}
setFacilitiesLogLevel(facilities, level);
opt->multiLog = true;
}
*pos = 0;
int facilities = parseLogFacilities(arg);
if (facilities == -1) {
argp_error(state, "invalid log: areas");
return EINVAL;
}
LogLevel level = parseLogLevel(pos + 1);
if (level == ll_COUNT) {
argp_error(state, "invalid log: level");
return EINVAL;
}
if (opt->logAreas != -1 || opt->logLevel != ll_COUNT) {
argp_error(state, "invalid log (combined with logareas or loglevel)");
return EINVAL;
}
setFacilitiesLogLevel(facilities, level);
opt->multiLog = true;
break;
}
case O_LOGARE: // --logareas=all
opt->logAreas = parseLogFacilities(arg);
if (opt->logAreas == -1) {
{
int facilities = parseLogFacilities(arg);
if (facilities == -1) {
argp_error(state, "invalid logareas");
return EINVAL;
}
@@ -600,9 +612,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
argp_error(state, "invalid logareas (combined with log)");
return EINVAL;
}
opt->logAreas = facilities;
break;
}
case O_LOGLEV: // --loglevel=notice
opt->logLevel = parseLogLevel(arg);
{
LogLevel logLevel = parseLogLevel(arg);
if (opt->logLevel == ll_COUNT) {
argp_error(state, "invalid loglevel");
return EINVAL;
@@ -611,7 +626,9 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
argp_error(state, "invalid loglevel (combined with log)");
return EINVAL;
}
opt->logLevel = logLevel;
break;
}
// Raw logging options:
case O_RAW: // --lograwdata
@@ -625,11 +642,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->logRawFile = arg;
break;
case O_RAWSIZ: // --lograwdatasize=100
opt->logRawSize = parseInt(arg, 10, 1, 1000000, &result);
value = parseInt(arg, 10, 1, 1000000, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid lograwdatasize");
return EINVAL;
}
opt->logRawSize = value;
break;
@@ -645,11 +663,12 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->dumpFile = arg;
break;
case O_DMPSIZ: // --dumpsize=100
opt->dumpSize = parseInt(arg, 10, 1, 1000000, &result);
value = parseInt(arg, 10, 1, 1000000, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid dumpsize");
return EINVAL;
}
opt->dumpSize = value;
break;
case O_DMPFLU: // --dumpflush
opt->dumpFlush = true;
@@ -1345,11 +1364,14 @@ int main(int argc, char* argv[]) {
strcat(envopt, pos);
}
int idx = -1;
s_opt.injectMessages = true; // for skipping unknown values
error_t err = argp_parse(&aargp, cnt, envargv, ARGP_PARSE_ARGV0|ARGP_SILENT|ARGP_IN_ORDER,
&idx, &s_opt);
s_opt.injectMessages = true; // for skipping unknown values via ARGP_ERR_UNKNOWN
error_t err = argp_parse(&aargp, cnt, envargv, ARGP_PARSE_ARGV0|ARGP_SILENT|ARGP_IN_ORDER, &idx, &s_opt);
if (err != 0 && idx == -1) { // ignore args for non-arg boolean options
logError(lf_main, "invalid/unknown argument in env: %s", envopt);
if (err == ESRCH) { // special value to abort immediately
logError(lf_main, "invalid argument in env: %s", envopt);
return EINVAL;
}
logError(lf_main, "invalid/unknown argument in env (ignored): %s", envopt);
}
s_opt.injectMessages = false; // restore (was not parsed from cmdline args yet)
}
+18 -16
View File
@@ -150,7 +150,7 @@ void splitFields(const string& str, vector<string>* row);
*/
static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
result_t result = RESULT_OK;
unsigned int value;
switch (key) {
case O_HOST: // --mqtthost=localhost
if (arg == nullptr || arg[0] == 0) {
@@ -161,11 +161,12 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
break;
case O_PORT: // --mqttport=1883
g_port = (uint16_t)parseInt(arg, 10, 1, 65535, &result);
value = parseInt(arg, 10, 1, 65535, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid mqttport");
return EINVAL;
}
g_port = (uint16_t)value;
break;
case O_CLID: // --mqttclientid=clientid
@@ -193,28 +194,28 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
break;
case O_TOPI: // --mqtttopic=ebusd
{
if (arg == nullptr || arg[0] == 0 || strchr(arg, '+') || arg[strlen(arg)-1] == '/') {
argp_error(state, "invalid mqtttopic");
return EINVAL;
} else {
char *pos = strchr(arg, '#');
if (pos && (pos == arg || pos[1])) { // allow # only at very last position (to indicate not using any default)
argp_error(state, "invalid mqtttopic");
return EINVAL;
}
}
char *pos = strchr(arg, '#');
if (pos && (pos == arg || pos[1])) { // allow # only at very last position (to indicate not using any default)
argp_error(state, "invalid mqtttopic");
return EINVAL;
}
if (g_topic) {
argp_error(state, "duplicate mqtttopic");
return EINVAL;
} else {
StringReplacer replacer;
if (!replacer.parse(arg, true)) {
argp_error(state, "malformed mqtttopic");
return EINVAL;
}
g_topic = arg;
}
StringReplacer replacer;
if (!replacer.parse(arg, true)) {
argp_error(state, "malformed mqtttopic");
return ESRCH; // abort in any case due to the above potentially being destructive
}
g_topic = arg;
break;
}
case O_GTOP: // --mqttglobal=global/
if (arg == nullptr || strchr(arg, '+') || strchr(arg, '#')) {
@@ -229,11 +230,12 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
break;
case O_PQOS: // --mqttqos=0
g_qos = parseSignedInt(arg, 10, 0, 2, &result);
value = parseInt(arg, 10, 0, 2, &result);
if (result != RESULT_OK) {
argp_error(state, "invalid mqttqos value");
return EINVAL;
}
g_qos = static_cast<signed>(value);
break;
case O_INTF: // --mqttint=/etc/ebusd/mqttint.cfg