commit 912e1d583ea18ed2c3ca1d1fd884ed1cce1825d8
parent 02621f745a3a9f8c2a809a8bceededa935c6f6d6
Author: Santtu Lakkala <inz@inz.fi>
Date: Thu, 6 Jul 2023 12:56:57 +0300
Add error handling and man page
Some error handling for configuration file parsing and shiny new manual
page.
Diffstat:
M | Makefile | | | 7 | +++++-- |
A | udyfi.8 | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | udyfi.c | | | 30 | ++++++++++++++++++++++-------- |
3 files changed, 145 insertions(+), 10 deletions(-)
diff --git a/Makefile b/Makefile
@@ -2,6 +2,7 @@ CFLAGS ?= -Os
CFLAGS += -W -Wall -std=c99 -pedantic -D_POSIX_C_SOURCE=200809L
PREFIX ?= /usr/local
BINDIR := $(PREFIX)/bin
+MANDIR := $(PREFIX)/share/man/man8
IFADDRS_CFLAGS ?= -DUSE_IFADDRS
HEADERS = arg.h config.h
VERSION=0.1.0
@@ -16,8 +17,8 @@ LIBS := -L/usr/local/lib -ltls
all: udyfi
config.h: config.def.h
- if test -f "$@"; then echo "Refusing to overwrite old config.h"; false; fi
- cp $< $@
+ if test -f "$@"; then echo "Refusing to overwrite old config.h; please remove or update manually"; false; fi
+ cp config.def.h $@
udyfi: udyfi.c $(HEADERS)
$(CROSS)$(CC) -DVERSION='"$(VERSION)"' $(CFLAGS) $(LIBTLS_CFLAGS) $(OPENSSL_CFLAGS) $(IFADDRS_CFLAGS) $< -o $@ $(LIBS)
@@ -28,3 +29,5 @@ clean:
install: udyfi
install -d $(DESTDIR)$(BINDIR)
install udyfi $(DESTDIR)$(BINDIR)
+ install -d $(DESTDIR)$(MANDIR)
+ install udyfi.8 $(DESTDIR)$(MANDIR)
diff --git a/udyfi.8 b/udyfi.8
@@ -0,0 +1,118 @@
+.Dd Jul 6, 2023
+.Dt UDYFI 8
+.Os
+.
+.Sh NAME
+.Nm udyfi
+.Nd dynamic dns updater daemon
+.
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl 4
+.Op Fl 6
+.Op Fl a Ar user-agent string
+.Op Fl d Ar dyndns server
+.Op Fl i Ar interface to bind to
+.Op Fl u Ar dyndns username
+.Op Fl p Ar dyndns password
+.Op Fl F Ar configuration file
+.Op Fl f Ar password file
+.Op Fl c Ar checkip server
+.Op Fl D Ar dyndns port
+.Op Fl C Ar checkip port
+.Op Fl b
+.Op Fl l Ar logfile
+.Op Fl P Ar pidfile
+.Op Fl U Ar run as user
+.Op Fl s
+.Op Fl S
+.Op Fl z
+.Op Fl Z
+.Ar domain names
+.Ek
+.
+.Sh DESCRIPTION
+.Bd -filled
+.Nm
+is a dynamic DNS updater daemon
+.Ed
+.
+.Sh OPTIONS
+udyfi options and default settings
+.Bl -tag -width Ds
+.
+.It Fl 4
+Operate over IPv4 only. (Default: any)
+.
+.It Fl 6
+Operate over IPv6 only. (Default: any)
+.
+.It Fl b
+Fork into background. (Default: don't fork)
+.
+.It Fl l Ar logfile
+Location for a log file (no default).
+.
+.It Fl a Ar user-agent string
+User-agent string used in requests (Default: udyfi/version)
+.
+.It Fl d Ar dyndns server
+Dynamic DNS server to connect to (Default: dy.fi)
+.
+.It Fl i Ar interface to bind to
+Interface or address to connect from (Default: any)
+.
+.It Fl u Ar dyndns username
+Username for the dynamic DNS service
+.
+.It Fl p Ar dyndns password
+Password for the dynamic DNS service
+.
+.It Fl F Ar configuration file
+Read configuration from file
+.
+.It Fl f Ar password file
+Read password from file
+.
+.It Fl c Ar checkip server
+Checkip service to check public IP from (Default: checkip.dy.fi)
+.
+.It Fl D Ar dyndns port
+Dynamic DNS server port (Default: 80 for HTTP, 443 for HTTPS)
+.
+.It Fl C Ar checkip port
+Checkip server port (Default: 80 for HTTP, 443 for HTTPS)
+.
+.It Fl P Ar pidfile
+Write daemon pid to pidfile (Default: none)
+.
+.It Fl U Ar run as user
+Change to user after startup (Default: none)
+.
+.It Fl s
+Connect to dynamic DNS server over HTTPS (Default: yes)
+.
+.It Fl S
+Connect to checkip server over HTTPS (Default: no)
+.
+.It Fl z
+Connect to dynamic DNS server over HTTP (Default: no)
+.
+.It Fl Z
+Connect to checkip server over HTTP (Default: yes)
+.
+.It Ar domain names
+Comma-separated list of domain names to update
+.
+.It
+At minimum, username, password and at least one domain name needs to be
+specified, either on command line, or in a configuration file.
+.
+.Sh CONFIGURATION FILE
+.Bd -filled
+The configuration file is a single-line file consisting of command line
+arguments. The arguments are processed in-place, overriding arguments
+specified before, and overridden by arguments after. Multiple files may
+be read sequentially, but cannot be nested. Basic quotation is supported.
+.
diff --git a/udyfi.c b/udyfi.c
@@ -75,7 +75,7 @@ static char **strsplit(char *s, int *c)
char *r = s;
char *w = s;
char **rv = malloc((n + 1) * sizeof(*rv));
- enum { NONE, SQUOT = '\'', DQUOT = '"' } state = NONE;
+ enum { NONE, ERR, SQUOT = '\'', DQUOT = '"' } state = NONE;
rv[0] = s;
@@ -108,12 +108,21 @@ static char **strsplit(char *s, int *c)
continue;
case '\\':
- if (state != SQUOT)
- r++;
+ if (state != SQUOT) {
+ if (!*++r) {
+ state = ERR;
+ continue;
+ }
+ }
break;
}
*w++ = *r++;
}
+
+ if (state != NONE) {
+ free(rv);
+ return NULL;
+ }
*w = '\0';
rv[n] = NULL;
*c = n;
@@ -701,11 +710,11 @@ cfgtoggle:
dropuser = EARGF(usage());
break;
case 'p': {
- char *pass = EARGF(usage());
- snprintf(password, sizeof(password),
- "%s", pass);
- memset(pass, 0, strlen(pass));
- break;
+ char *pass = EARGF(usage());
+ snprintf(password, sizeof(password),
+ "%s", pass);
+ memset(pass, 0, strlen(pass));
+ break;
}
case 'F': {
FILE *f;
@@ -744,6 +753,11 @@ cfgtoggle:
cfgfile.arg = arg;
argv = strsplit(data, &argc);
+ if (!argv) {
+ fprintf(stderr, "Failed to parse configuration file\n");
+ free(data);
+ return EXIT_FAILURE;
+ }
arg = argv[0];
if (*arg != '-')
continue;