Support most config options in defaults file

This commit is contained in:
Jan-Piet Mens
2016-02-25 17:29:39 +01:00
parent a4ab3599d2
commit 25ff5ceca3
5 changed files with 217 additions and 44 deletions
+29 -1
View File
@@ -369,6 +369,33 @@ As mentioned earlier, data is stored in files, and these files are relative to `
You should definitely **not** modify or touch these files: they remain under the control of the _recorder_. You can of course, remove old `.rec` files if they consume too much space.
## Configuration file
The recorder attempts to read its startup configuration from a configuration file; the path to this is compiled into the Recorder (typically `/etc/defaults/ot-recorder`). The format of this file approximates that of a shell script with variables to be exported (the intention is so that it can be sourced by a shell script). Lines beginning with an octothorp (`#`) are ignored as are blank lines. Configuration settings proper are set as follows (note that some older versions of _libconfig_ require a trailing semicolon (`;`) on assignment:
```
OTR_STORAGEDIR="/var/spool/owntracks/recorder/store"
```
The following configuration settings may be applied (a `Y` in column `$` means an environment variable of the same name overrides a setting in the config file):
| Variable | $ | Default | Usage
| --------------------- | :--- | :------------ | ---------------
| `OTR_STORAGEDIR` | Y | compiled in | Pathname to the storage directory
| `OTR_HOST` | Y | `localhost` | MQTT hostname/address to connect to
| `OTR_PORT` | Y | `1883` | MQTT port number to connect to
| `OTR_USER` | Y | | MQTT username
| `OTR_PASS` | Y | | MQTT password
| `OTR_QOS` | | `2` | MQTT QoS
| `OTR_HTTPHOST` | | `localhost` | Address for the HTTP module to bind to
| `OTR_HTTPPORT` | | `8083` | Port number of the HTTP module to bind to
| `OTR_LUASCRIPT` | | | Path to the Lua script
| `OTR_PRECISION` | | `7` | Reverse-geo precision
| `OTR_GEOKEY` | | | API key for reverse-geo lookups
| `OTR_TOPICS` | | | String containing a space-separated list of topics to subscribe to for MQTT (overrides command-line arguments)
Note that options passed to `ot-recorder` override both configuration file settings and environment variables.
## Reverse Geo
@@ -625,7 +652,8 @@ After running `otr_hook()`, the _recorder_ attempts to invoke a Lua function for
You define a hooklet function only if you're interested in expressly triggering on a particular JSON element.
#### Environment
### Environment
The following environment variables control _ocat_'s behaviour:
+65
View File
@@ -4,4 +4,69 @@
# and its associated utilities to override compiled-in defaults.
# *** In libconfig versions < 1.4 a trailing semicolon is mandatory
# -----------------------------------------------------
# Storage directory
#
# OTR_STORAGEDIR = "/var/spool/owntracks/recorder/store"
# -----------------------------------------------------
# Address or hostname of the MQTT broker
#
# OTR_HOST="localhost"
# -----------------------------------------------------
# Port number of the MQTT broker
#
# OTR_PORT=1883
# -----------------------------------------------------
# Username for the MQTT connection
#
# OTR_USER=""
# -----------------------------------------------------
# Password for the MQTT connection
#
# OTR_PASS=""
# -----------------------------------------------------
# QoS for MQTT connection
#
# OTR_QOS=2
# -----------------------------------------------------
# Address for the HTTP module to bind to (default: localhost)
#
# OTR_HTTPHOST="localhost"
# -----------------------------------------------------
# Port number for the HTTP module to bind to (default: 8083)
#
# OTR_HTTPPORT=8083
# -----------------------------------------------------
# API key for reverse-geo lookups
#
# OTR_GEOKEY=""
# -----------------------------------------------------
# Reverse geo precision
#
# OTR_PRECISION=7
# -----------------------------------------------------
# List of topics for MQTT to subscribe to, blank separated in a string
#
# OTR_TOPICS="owntracks/+/+"
+66
View File
@@ -101,6 +101,7 @@ void get_defaults(char *filename, struct udata *ud)
{
config_t cfg, *cf;
const char *value;
int ival;
if (access(filename, R_OK) == -1)
return;
@@ -118,6 +119,71 @@ void get_defaults(char *filename, struct udata *ud)
if (config_lookup_string(cf, "OTR_STORAGEDIR", &value) != CONFIG_FALSE)
strcpy(STORAGEDIR, value);
#if WITH_MQTT
if (config_lookup_string(cf, "OTR_HOST", &value) != CONFIG_FALSE) {
if (ud->hostname) free(ud->hostname);
ud->hostname = strdup(value);
}
if (config_lookup_int(cf, "OTR_PORT", &ival) != CONFIG_FALSE) {
ud->port = ival;
}
if (config_lookup_string(cf, "OTR_USER", &value) != CONFIG_FALSE) {
if (ud->username) free(ud->username);
ud->username = strdup(value);
}
if (config_lookup_string(cf, "OTR_PASS", &value) != CONFIG_FALSE) {
if (ud->password) free(ud->password);
ud->password = strdup(value);
}
if (config_lookup_int(cf, "OTR_QOS", &ival) != CONFIG_FALSE) {
ud->qos = ival;
}
/* Topics is a blank-separated string of words; split and add to JSON array */
if (config_lookup_string(cf, "OTR_TOPICS", &value) != CONFIG_FALSE) {
char *parts[40];
int np, n;
if (ud->topics) json_delete(ud->topics);
if ((np = splitter((char *)value, " ", parts)) < 1) {
olog(LOG_ERR, "Illegal value in OTR_TOPICS");
exit(2);
}
ud->topics = json_mkarray();
for (n = 0; n < np; n++) {
json_append_element(ud->topics, json_mkstring(parts[n]));
}
splitterfree(parts);
}
#endif /* WITH_MQTT */
if (config_lookup_string(cf, "OTR_GEOKEY", &value) != CONFIG_FALSE) {
if (ud->geokey) free(ud->geokey);
ud->geokey = strdup(value);
}
if (config_lookup_int(cf, "OTR_PRECISION", &ival) != CONFIG_FALSE) {
geohash_setprec(ival);
printf("PREC=%d\n", geohash_prec());
}
#if WITH_HTTP
if (config_lookup_string(cf, "OTR_HTTPHOST", &value) != CONFIG_FALSE) {
if (ud->http_host) free(ud->http_host);
ud->http_host = strdup(value);
}
if (config_lookup_int(cf, "OTR_HTTPPORT", &ival) != CONFIG_FALSE) {
ud->http_port = ival;
}
#endif /* WITH_HTTP */
#if WITH_LUA
if (config_lookup_string(cf, "OTR_LUASCRIPT", &value) != CONFIG_FALSE) {
if (ud->luascript) free(ud->luascript);
ud->luascript = strdup(value);
}
#endif
config_destroy(cf);
}
+50 -43
View File
@@ -1112,33 +1112,31 @@ int main(int argc, char **argv)
{
#if WITH_MQTT
struct mosquitto *mosq = NULL;
char *username, *password, *cafile;
char *hostname = strdup("localhost");
int port = 1883;
char *cafile;
UT_string *clientid;
int rc, i;
struct utsname uts;
#endif /* WITH_MQTT */
char err[1024], *p;
char *logfacility = "local0";
#ifdef WITH_LUA
char *luascript = NULL;
#endif
#if WITH_MQTT
int loop_timeout = 1000;
#endif
int ch, initialize = FALSE;
static struct udata udata, *ud = &udata;
#ifdef WITH_HTTP
int http_port = 8083;
char *doc_root = DOCROOT;
char *http_host = strdup("localhost");
#endif
char *progname = *argv;
#if WITH_MQTT
udata.qos = DEFAULT_QOS;
udata.pubprefix = NULL;
udata.username = NULL;
udata.password = NULL;
udata.hostname = strdup("localhost");
udata.port = 1883;
udata.topics = NULL;
#endif
udata.ignoreretained = TRUE;
udata.skipdemo = TRUE;
@@ -1149,8 +1147,11 @@ int main(int argc, char **argv)
udata.t2t = NULL; /* Topic to TID */
#ifdef WITH_HTTP
udata.mgserver = NULL;
udata.http_host = strdup("localhost");
udata.http_port = 8083;
#endif
#ifdef WITH_LUA
udata.luascript = NULL;
udata.luadata = NULL;
udata.luadb = NULL;
#endif /* WITH_LUA */
@@ -1162,13 +1163,14 @@ int main(int argc, char **argv)
get_defaults(CONFIGFILE, &udata);
#if WITH_MQTT
if ((p = getenv("OTR_HOST")) != NULL) {
hostname = strdup(p);
ud->hostname = strdup(p);
}
if ((p = getenv("OTR_PORT")) != NULL) {
port = atoi(p);
ud->port = atoi(p);
}
#endif
@@ -1177,6 +1179,9 @@ int main(int argc, char **argv)
}
#if WITH_MQTT
ud->username = getenv("OTR_USER");
ud->password = getenv("OTR_PASS");
utstring_new(clientid);
utstring_printf(clientid, "ot-recorder");
if (uname(&uts) == 0) {
@@ -1228,6 +1233,7 @@ int main(int argc, char **argv)
udata.debug = TRUE;
break;
case 12:
if (udata.geokey) free(udata.geokey);
udata.geokey = strdup(optarg);
break;
case 11:
@@ -1245,7 +1251,8 @@ int main(int argc, char **argv)
break;
#ifdef WITH_LUA
case 7:
luascript = strdup(optarg);
if (ud->luascript) free(ud->luascript);
ud->luascript = strdup(optarg);
break;
#endif
#ifdef WITH_MQTT
@@ -1267,11 +1274,11 @@ int main(int argc, char **argv)
ud->ignoreretained = FALSE;
break;
case 'H':
free(hostname);
hostname = strdup(optarg);
free(ud->hostname);
ud->hostname = strdup(optarg);
break;
case 'p':
port = atoi(optarg);
ud->port = atoi(optarg);
break;
#endif /* WITH_MQTT */
case 5:
@@ -1282,14 +1289,14 @@ int main(int argc, char **argv)
break;
#ifdef WITH_HTTP
case 'A': /* API */
http_port = atoi(optarg);
ud->http_port = atoi(optarg);
break;
case 2: /* no short char */
doc_root = strdup(optarg);
break;
case 3: /* no short char */
free(http_host);
http_host = strdup(optarg);
free(ud->http_host);
ud->http_host = strdup(optarg);
break;
#endif
case 'D':
@@ -1369,19 +1376,27 @@ int main(int argc, char **argv)
argv += (optind);
#ifdef WITH_MQTT
if (argc < 1) {
if (ud->topics == NULL && argc < 1) { /* no topics set via config file */
usage(progname);
return (-1);
}
/*
* Push list of topics into the array so that we can (re)subscribe
* in on_connect()
*/
if (ud->topics == NULL) {
ud->topics = json_mkarray();
for (i = 0; i < argc; i++) {
json_append_element(ud->topics, json_mkstring(argv[i]));
}
}
#endif
#ifdef WITH_MQTT
username = getenv("OTR_USER");
password = getenv("OTR_PASS");
#endif /* WITH_MQTT */
#ifdef WITH_HTTP
if (http_port) {
if (ud->http_port) {
if (!is_directory(doc_root)) {
olog(LOG_ERR, "%s is not a directory", doc_root);
exit(1);
@@ -1423,9 +1438,9 @@ int main(int argc, char **argv)
* If option for lua-script has not been given, ignore all hooks.
*/
if (luascript) {
if ((udata.luadata = hooks_init(ud, luascript)) == NULL) {
olog(LOG_ERR, "Stopping because Lua load failed");
if (ud->luascript) {
if ((udata.luadata = hooks_init(ud, ud->luascript)) == NULL) {
olog(LOG_ERR, "Stopping because loading of Lua script %s failed", ud->luascript);
exit(1);
}
}
@@ -1451,14 +1466,6 @@ int main(int argc, char **argv)
return 1;
}
/*
* Pushing list of topics into the array so that we can (re)subscribe on_connect()
*/
ud->topics = json_mkarray();
for (i = 0; i < argc; i++) {
json_append_element(ud->topics, json_mkstring(argv[i]));
}
mosquitto_reconnect_delay_set(mosq,
2, /* delay */
@@ -1469,8 +1476,8 @@ int main(int argc, char **argv)
mosquitto_connect_callback_set(mosq, on_connect);
mosquitto_disconnect_callback_set(mosq, on_disconnect);
if (username && password) {
mosquitto_username_pw_set(mosq, username, password);
if (ud->username && ud->password) {
mosquitto_username_pw_set(mosq, ud->username, ud->password);
}
cafile = getenv("OTR_CAFILE");
@@ -1499,11 +1506,11 @@ int main(int argc, char **argv)
}
olog(LOG_INFO, "connecting to MQTT on %s:%d as clientID %s %s TLS",
hostname, port,
ud->hostname, ud->port,
UB(clientid),
(cafile) ? "with" : "without");
rc = mosquitto_connect(mosq, hostname, port, 60);
rc = mosquitto_connect(mosq, ud->hostname, ud->port, 60);
if (rc) {
if (rc == MOSQ_ERR_ERRNO) {
strerror_r(errno, err, 1024);
@@ -1518,11 +1525,11 @@ int main(int argc, char **argv)
#endif /* WITH_MQTT */
#ifdef WITH_HTTP
if (http_port) {
if (ud->http_port) {
char address[BUFSIZ];
const char *addressinfo;
sprintf(address, "%s:%d", http_host, http_port);
sprintf(address, "%s:%d", ud->http_host, ud->http_port);
mg_set_option(udata.mgserver, "listening_port", address);
// mg_set_option(udata.mgserver, "listening_port", "8090,ssl://8091:cert.pem");
@@ -1583,6 +1590,7 @@ int main(int argc, char **argv)
#ifdef WITH_HTTP
mg_destroy_server(&udata.mgserver);
free(ud->http_host);
#endif
#if WITH_LUA
@@ -1596,9 +1604,8 @@ int main(int argc, char **argv)
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
free(hostname);
free(ud->hostname);
#endif
free(http_host);
return (0);
}
+7
View File
@@ -15,6 +15,10 @@ struct udata {
#if WITH_MQTT
char *pubprefix; /* If not NULL (default), republish modified payload to <pubprefix>/topic */
int qos; /* Subscribe QoS */
char *hostname; /* MQTT broker */
int port; /* MQTT port */
char *username; /* MQTT user */
char *password; /* MQTT password */
#endif
int skipdemo; /* True if _demo users are to be skipped */
int revgeo; /* True (default) if we should do reverse Geo lookups */
@@ -24,8 +28,11 @@ struct udata {
struct gcache *t2t; /* topic to tid */
#ifdef WITH_HTTP
struct mg_server *mgserver; /* Mongoose */
char *http_host; /* address of http bind */
int http_port; /* port number for above */
#endif
#ifdef WITH_LUA
char *luascript; /* Path to Lua script */
struct luadata *luadata; /* Lua stuff */
struct gcache *luadb; /* lmdb named database 'luadb' */
#endif