Replace rdline with libbsd fparseln

Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
David Oberhollenzer 2019-04-03 23:41:09 +02:00
parent a02ef642bd
commit 10b4195af2
5 changed files with 73 additions and 97 deletions

View File

@ -5,7 +5,16 @@ AM_CFLAGS = $(WARN_CFLAGS)
sbin_PROGRAMS = gcrond
gcrond_SOURCES = gcrond.c gcrond.h rdcron.c crontab.c cronscan.c rdline.c
gcrond_SOURCES = gcrond.c gcrond.h rdcron.c crontab.c cronscan.c
gcrond_CPPFLAGS = $(AM_CPPFLAGS)
gcrond_CFLAGS = $(AM_CFLAGS)
gcrond_LDADD =
if HAVE_LIBBSD
gcrond_CPPFLAGS += -DHAVE_LIBBSD
gcrond_CFLAGS += $(LIBBSD_CFLAGS)
gcrond_LDADD += $(LIBBSD_LIBS)
endif
crontabdir = @GCRONDIR@
crontab_DATA = crontab/0-example

View File

@ -8,6 +8,23 @@ AC_PROG_CC
AC_PROG_CC_C99
AC_PROG_INSTALL
AC_PROG_RANLIB
AC_CANONICAL_HOST
m4_ifndef([PKG_PROG_PKG_CONFIG],
[m4_fatal([Could not locate the pkg-config autoconf
macros. These are usually located in /usr/share/aclocal/pkg.m4.
If your macros are in a different location, try setting the
environment variable AL_OPTS="-I/other/macro/dir" before running
./autogen.sh or autoreconf again. Make sure pkg-config is installed.])])
PKG_PROG_PKG_CONFIG
case "${host_os}" in
linux*)
AM_CONDITIONAL([HAVE_LIBBSD], [true])
PKG_CHECK_MODULES(LIBBSD, [libbsd], [],
[AC_MSG_ERROR([missing libbsd])])
;;
esac
UL_WARN_ADD([-Wall])
UL_WARN_ADD([-Wextra])

View File

@ -21,6 +21,10 @@
#include <fcntl.h>
#include <time.h>
#ifdef HAVE_LIBBSD
#include <bsd/bsd.h>
#endif
#include "config.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@ -43,14 +47,6 @@ typedef struct {
char *line;
} rdline_t;
int rdline_init(rdline_t *t, int dirfd, const char *filename);
void rdline_complain(rdline_t *t, const char *msg, ...);
void rdline_cleanup(rdline_t *t);
int rdline(rdline_t *t);
crontab_t *rdcron(int dirfd, const char *filename);
void delcron(crontab_t *cron);

View File

@ -96,6 +96,10 @@ static const struct {
/*****************************************************************************/
#define complainf(rd, msg, ...) \
fprintf(stderr, "%s: %zu: " msg "\n", \
rd->filename, rd->lineno, __VA_ARGS__)
static char *readnum(char *line, int *out, int minval, int maxval,
const enum_map_t *mnemonic, rdline_t *rd)
{
@ -113,7 +117,7 @@ static char *readnum(char *line, int *out, int minval, int maxval,
}
if (ev->name == NULL) {
rdline_complain(rd, "unexpected '%.*s'", i, line);
complainf(rd, "unexpected '%.*s'", i, line);
return NULL;
}
@ -138,13 +142,14 @@ static char *readnum(char *line, int *out, int minval, int maxval,
*out = value;
return line;
fail_of:
rdline_complain(rd, "value exceeds maximum (%d > %d)", value, maxval);
complainf(rd, "value exceeds maximum (%d > %d)", value, maxval);
return NULL;
fail_uf:
rdline_complain(rd, "value too small (%d < %d)", value, minval);
complainf(rd, "value too small (%d < %d)", value, minval);
return NULL;
fail_mn:
rdline_complain(rd, "expected numeric value");
fprintf(stderr, "%s: %zu: expected numeric value\n",
rd->filename, rd->lineno);
return NULL;
}
@ -201,7 +206,8 @@ next:
return line;
fail:
rdline_complain(rd, "invalid time range expression");
fprintf(stderr, "%s: %zu: invalid time range expression\n",
rd->filename, rd->lineno);
return NULL;
}
@ -229,7 +235,7 @@ static char *cron_interval(crontab_t *cron, rdline_t *rd)
*cron = intervals[i].tab;
return rd->line + j;
fail:
rdline_complain(rd, "unknown interval '%.*s'", (int)j, rd->line);
complainf(rd, "unknown interval '%.*s'", (int)j, rd->line);
return NULL;
}
@ -266,14 +272,39 @@ crontab_t *rdcron(int dirfd, const char *filename)
crontab_t *cron, *list = NULL;
rdline_t rd;
char *ptr;
int fd;
if (rdline_init(&rd, dirfd, filename))
memset(&rd, 0, sizeof(rd));
rd.filename = filename;
fd = openat(dirfd, filename, O_RDONLY);
if (fd == -1) {
perror(filename);
return NULL;
}
rd.fp = fdopen(fd, "r");
if (rd.fp == NULL) {
perror("fdopen");
close(fd);
return NULL;
}
for (;;) {
free(rd.line);
errno = 0;
rd.line = fparseln(rd.fp, NULL, &rd.lineno, NULL, 0);
if (rd.line == NULL) {
if (errno)
perror(filename);
break;
}
while (rdline(&rd) == 0) {
cron = calloc(1, sizeof(*cron));
if (cron == NULL) {
rdline_complain(&rd, strerror(errno));
perror(filename);
break;
}
@ -293,7 +324,7 @@ crontab_t *rdcron(int dirfd, const char *filename)
cron->exec = strdup(ptr);
if (cron->exec == NULL) {
rdline_complain(&rd, strerror(errno));
perror(filename);
free(cron);
continue;
}
@ -302,6 +333,6 @@ crontab_t *rdcron(int dirfd, const char *filename)
list = cron;
}
rdline_cleanup(&rd);
fclose(rd.fp);
return list;
}

View File

@ -1,77 +0,0 @@
/* SPDX-License-Identifier: ISC */
#include "gcrond.h"
int rdline(rdline_t *t)
{
size_t i, len;
do {
free(t->line);
t->line = NULL;
errno = 0;
len = 0;
if (getline(&t->line, &len, t->fp) < 0) {
if (errno) {
rdline_complain(t, strerror(errno));
return -1;
}
return 1;
}
t->lineno += 1;
for (i = 0; isspace(t->line[i]); ++i)
;
if (t->line[i] == '\0' || t->line[i] == '#') {
t->line[0] = '\0';
} else if (i) {
memmove(t->line, t->line + i, len - i + 1);
}
} while (t->line[0] == '\0');
return 0;
}
void rdline_complain(rdline_t *t, const char *msg, ...)
{
va_list ap;
fprintf(stderr, "%s: %zu: ", t->filename, t->lineno);
va_start(ap, msg);
vfprintf(stderr, msg, ap);
va_end(ap);
fputc('\n', stderr);
}
int rdline_init(rdline_t *t, int dirfd, const char *filename)
{
int fd;
memset(t, 0, sizeof(*t));
fd = openat(dirfd, filename, O_RDONLY);
if (fd == -1) {
perror(filename);
return -1;
}
t->fp = fdopen(fd, "r");
if (t->fp == NULL) {
perror("fdopen");
close(fd);
return -1;
}
t->filename = filename;
return 0;
}
void rdline_cleanup(rdline_t *t)
{
free(t->line);
fclose(t->fp);
}