aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-02-23 23:31:26 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-02-23 23:31:26 +0200
commitb42866f337ced2942eca3d02a23813536c108452 (patch)
tree94f11eded557ee16fa20b8bf359d468e10ef8b44 /src
parentd9dfecfa5f1d8e217f1f8a05a261afa5b5f4d6cd (diff)
downloadping903-b42866f337ced2942eca3d02a23813536c108452.tar.gz
ping903-b42866f337ced2942eca3d02a23813536c108452.tar.bz2
Save local additions in a local ip list file. Read it at startup.
* src/config.c (file_read_ip_list): New function. * src/defs.h (LOCAL_IP_LIST_FILE): New definition. * src/ping903.h (file_read_ip_list): New proto. * src/pinger.c (conf_hostping_count) (hostping_updated): New static variables. (hostping_add,hostping_delete): Raise the hostping_updated flag. (p903_init): Read in the local ip-list file, if it exists. Clear hostping_updated. (p903_scheduler): Save changes to the local ip-list file, if hostping_updated is set.
Diffstat (limited to 'src')
-rw-r--r--src/config.c28
-rw-r--r--src/defs.h13
-rw-r--r--src/ping903.h3
-rw-r--r--src/pinger.c111
4 files changed, 141 insertions, 14 deletions
diff --git a/src/config.c b/src/config.c
index f2376a5..8a5028a 100644
--- a/src/config.c
+++ b/src/config.c
@@ -47,12 +47,8 @@ static int
cf_ip_list_parse(union cf_callback_arg *arg, void *data)
{
FILE *fp;
- char buf[1024];
- unsigned ln = 0;
- int skip_to_eol = 0;
- int ret = CF_RET_OK;
- struct addrinfo hints;
-
+ int rc;
+
fp = fopen(arg->input.val, "r");
if (!fp) {
error("%s:%d: can't open file %s: %s",
@@ -60,7 +56,20 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data)
arg->input.val, strerror(errno));
exit(1);
}
-
+ rc = file_read_ip_list(fp, arg->input.val);
+ fclose(fp);
+ return rc;
+}
+
+int
+file_read_ip_list(FILE *fp, char const *fname)
+{
+ char buf[1024];
+ unsigned ln = 0;
+ int skip_to_eol = 0;
+ int ret = CF_RET_OK;
+ struct addrinfo hints;
+
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
@@ -84,7 +93,7 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data)
if (buf[len-1] == '\n')
buf[--len] = 0;
else if (!feof(fp)) {
- error("%s:%d: line too long", arg->input.val, ln);
+ error("%s:%d: line too long", fname, ln);
skip_to_eol = 1;
ret = CF_RET_FAIL;
continue;
@@ -102,14 +111,13 @@ cf_ip_list_parse(union cf_callback_arg *arg, void *data)
rc = getaddrinfo(p, NULL, &hints, &res);
if (rc) {
- error("%s:%d: invalid IP address", arg->input.val, ln);
+ error("%s:%d: invalid IP address", fname, ln);
ret = CF_RET_FAIL;
continue;
}
hostping_add(p, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
}
- fclose(fp);
return ret;
}
diff --git a/src/defs.h b/src/defs.h
index d41c9a8..17b1b1b 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -6,9 +6,18 @@
#ifndef DEFAULT_SERVICE
# define DEFAULT_SERVICE "8080"
#endif
-#ifndef DEFAULT_CONFIG_FILE
-# define DEFAULT_CONFIG_FILE "/etc/ping903.conf"
+#ifndef SYSCONFDIR
+# define SYSCONFDIR "/etc"
#endif
+#ifndef LOCALSTATEDIR
+# define LOCALSTATEDIR "/var/lib"
+#endif
+#ifndef PACKAGESTATEDIR
+# define PACKAGESTATEDIR LOCALSTATEDIR "/" PACKAGE
+#endif
+#define DEFAULT_CONFIG_FILE SYSCONFDIR "/" PACKAGE ".conf"
+#define LOCAL_IP_LIST_FILE PACKAGESTATEDIR "/ip-list"
+
#define COPYLEFT "\
Copyright (C) 2020 Sergey Poznyakoff\n\
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
diff --git a/src/ping903.h b/src/ping903.h
index 2f2d7ef..e24e356 100644
--- a/src/ping903.h
+++ b/src/ping903.h
@@ -14,6 +14,7 @@
You should have received a copy of the GNU General Public License
along with Ping903. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <stdio.h>
#include <pthread.h>
#include <stdarg.h>
#include <microhttpd.h>
@@ -132,6 +133,8 @@ int get_all_host_stat(struct json_value **);
struct addrinfo;
int get_host_matches(struct addrinfo **aip, struct json_value **retval);
+int file_read_ip_list(FILE *fp, char const *fname);
+
void p903_init(void);
void *p903_sender(void *p);
void *p903_receiver(void *p);
diff --git a/src/pinger.c b/src/pinger.c
index 19572d5..2517781 100644
--- a/src/pinger.c
+++ b/src/pinger.c
@@ -18,6 +18,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/stat.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -28,6 +29,7 @@
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
+#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <limits.h>
@@ -100,6 +102,8 @@ timespec_incr(struct timespec *a, struct timespec const *b)
static HOSTPING *hostping_head, *hostping_tail;
static size_t hostping_count;
static pthread_rwlock_t hostping_rwlock = PTHREAD_RWLOCK_INITIALIZER;
+static size_t conf_hostping_count;
+static int hostping_updated;
void
hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen)
@@ -122,6 +126,7 @@ hostping_add(char const *name, struct sockaddr *addr, socklen_t addrlen)
hostping_tail = hp;
hostping_count++;
+ hostping_updated = 1;
}
void
@@ -136,7 +141,8 @@ hostping_delete(HOSTPING *hp)
else
hostping_tail = hp->prev;
hostping_count--;
-
+ hostping_updated = 1;
+
free(hp->name);
free(hp->addr);
pthread_mutex_destroy(&hp->mutex);
@@ -611,11 +617,26 @@ p903_init(void)
{
struct protoent *proto;
int i;
+ FILE *fp;
+
+ conf_hostping_count = hostping_count;
+ fp = fopen(LOCAL_IP_LIST_FILE, "r");
+ if (fp) {
+ int rc = file_read_ip_list(fp, LOCAL_IP_LIST_FILE);
+ if (rc == CF_RET_FAIL)
+ exit(1);
+ fclose(fp);
+ } else if (errno != ENOENT) {
+ fatal("can't open %s: %s", LOCAL_IP_LIST_FILE,
+ strerror(errno));
+ exit(1);
+ }
if (hostping_count == 0) {
info("no IP addresses configured, starting anyway");
}
-
+ hostping_updated = 0;
+
proto = getprotobyname("icmp");
if (!proto) {
fatal("no entry for icmp in the system protocol database");
@@ -943,6 +964,91 @@ p903_receiver(void *p)
}
}
+static int
+create_dirs(char const *filename)
+{
+ char *namebuf;
+ char *p;
+ char *endp;
+ struct stat st;
+ size_t len;
+
+ p = strrchr(filename, '/');
+ if (!p)
+ return -1;
+ len = p - filename;
+ namebuf = malloc(len + 1);
+ if (!namebuf)
+ return -1;
+ memcpy(namebuf, filename, len);
+ namebuf[len] = 0;
+ endp = namebuf + len;
+
+ while ((p = strrchr(namebuf, '/')) != NULL && p > namebuf) {
+ *p = 0;
+ if (stat(namebuf, &st)) {
+ if (errno == ENOENT)
+ continue;
+ error("can't stat %s: %s", namebuf, strerror(errno));
+ goto err;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ break;
+ } else {
+ error("file name component %s is not a directory",
+ namebuf);
+ goto err;
+ }
+ }
+
+ while (p < endp) {
+ *p = '/';
+ if (mkdir(namebuf, 0755)) {
+ error("can't create directory %s: %s",
+ namebuf, strerror(errno));
+ goto err;
+ }
+ p = p + strlen(p);
+ }
+ return 0;
+err:
+ free(namebuf);
+ return -1;
+}
+
+static void
+save_local_ip_list(void)
+{
+ FILE *fp;
+ HOSTPING *hp;
+ size_t i;
+
+ if (!hostping_updated)
+ return;
+ fp = fopen(LOCAL_IP_LIST_FILE, "w");
+ if (!fp) {
+ if (errno == ENOENT) {
+ create_dirs(LOCAL_IP_LIST_FILE);
+ fp = fopen(LOCAL_IP_LIST_FILE, "w");
+ }
+ if (!fp) {
+ fatal("can't open %s for writing: %s",
+ LOCAL_IP_LIST_FILE,
+ strerror(errno));
+ return;
+ }
+ }
+ i = 0;
+ FOR_EACH_HOSTPING(hp) {
+ if (i >= conf_hostping_count)
+ fprintf(fp, "%s\n", hp->name);
+ i++;
+ }
+ fclose(fp);
+
+ hostping_updated = 0;
+}
+
void *
p903_scheduler(void *p)
{
@@ -954,6 +1060,7 @@ p903_scheduler(void *p)
FOR_EACH_HOSTPING(hp) {
hostping_reset(hp);
}
+ save_local_ip_list();
pthread_rwlock_unlock(&hostping_rwlock);
start_probe();

Return to:

Send suggestions and report system problems to the System administrator.