mirror of
https://github.com/pygos/init.git
synced 2024-11-22 03:09:46 +01:00
Configuration parser cleanup
- Do a getline() & process in rdline instead of doing a read per character and feeding it through a state machine. - Move splitkv to rdcfg.c, the only place where it is used Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
This commit is contained in:
parent
7b647eefef
commit
24c90b7700
8 changed files with 176 additions and 218 deletions
|
@ -41,7 +41,7 @@ static struct entry *parse_list(rdline_t *rd)
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
while (rdline(rd) == 0) {
|
while (rdline(rd) == 0) {
|
||||||
ptr = rd->buffer;
|
ptr = rd->line;
|
||||||
|
|
||||||
while (*ptr != '\0' && *ptr != ' ' && *ptr != '=')
|
while (*ptr != '\0' && *ptr != ' ' && *ptr != '=')
|
||||||
++ptr;
|
++ptr;
|
||||||
|
@ -66,11 +66,11 @@ static struct entry *parse_list(rdline_t *rd)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = calloc(1, sizeof(*e) + strlen(rd->buffer) + 1);
|
e = calloc(1, sizeof(*e) + strlen(rd->line) + 1);
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
goto fail_oom;
|
goto fail_oom;
|
||||||
|
|
||||||
strcpy(e->data, rd->buffer);
|
strcpy(e->data, rd->line);
|
||||||
e->next = list;
|
e->next = list;
|
||||||
list = e;
|
list = e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ libinit_a_SOURCES += lib/util/print_version.c lib/util/argv_exec.c $(HEADRS)
|
||||||
libinit_a_CPPFLAGS = $(AM_CPPFLAGS)
|
libinit_a_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
libinit_a_CFLAGS = $(AM_CFLAGS)
|
libinit_a_CFLAGS = $(AM_CFLAGS)
|
||||||
|
|
||||||
libcfg_a_SOURCES = lib/libcfg/rdline.c lib/libcfg/unescape.c
|
libcfg_a_SOURCES = lib/libcfg/rdline.c lib/libcfg/unescape.c lib/libcfg/rdcfg.c
|
||||||
libcfg_a_SOURCES += lib/libcfg/splitkv.c lib/libcfg/rdcfg.c
|
|
||||||
libcfg_a_SOURCES += lib/libcfg/pack_argv.c lib/include/libcfg.h
|
libcfg_a_SOURCES += lib/libcfg/pack_argv.c lib/include/libcfg.h
|
||||||
libcfg_a_CPPFLAGS = $(AM_CPPFLAGS)
|
libcfg_a_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
libcfg_a_CFLAGS = $(AM_CFLAGS)
|
libcfg_a_CFLAGS = $(AM_CFLAGS)
|
||||||
|
|
|
@ -486,7 +486,8 @@ crontab_t *rdcron(int dirfd, const char *filename)
|
||||||
cron = calloc(1, sizeof(*cron));
|
cron = calloc(1, sizeof(*cron));
|
||||||
if (cron == NULL) {
|
if (cron == NULL) {
|
||||||
fputs("out of memory\n", stderr);
|
fputs("out of memory\n", stderr);
|
||||||
goto out;
|
close(fd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cron->minute = 0xFFFFFFFFFFFFFFFFUL;
|
cron->minute = 0xFFFFFFFFFFFFFFFFUL;
|
||||||
|
@ -501,7 +502,6 @@ crontab_t *rdcron(int dirfd, const char *filename)
|
||||||
delcron(cron);
|
delcron(cron);
|
||||||
cron = NULL;
|
cron = NULL;
|
||||||
}
|
}
|
||||||
out:
|
rdline_cleanup(&rd);
|
||||||
close(fd);
|
|
||||||
return cron;
|
return cron;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,23 +20,16 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd; /* input file descriptor */
|
|
||||||
const char *argstr; /* if not NULL, read from this instead */
|
|
||||||
|
|
||||||
const char *filename; /* input file name */
|
const char *filename; /* input file name */
|
||||||
size_t lineno; /* current line number */
|
size_t lineno; /* current line number */
|
||||||
|
FILE *fp;
|
||||||
size_t i; /* buffer offset */
|
char *line;
|
||||||
char buffer[256]; /* current line, null-terminated */
|
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
const char *const *argv;
|
const char *const *argv;
|
||||||
|
|
||||||
bool string; /* inside a string? */
|
|
||||||
bool escape; /* reading an escape sequence? */
|
|
||||||
bool comment; /* inside a comment */
|
|
||||||
} rdline_t;
|
} rdline_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -63,6 +56,8 @@ typedef struct {
|
||||||
void rdline_init(rdline_t *t, int fd, const char *filename,
|
void rdline_init(rdline_t *t, int fd, const char *filename,
|
||||||
int argc, const char *const *argv);
|
int argc, const char *const *argv);
|
||||||
|
|
||||||
|
void rdline_cleanup(rdline_t *t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read from file until end-of-file or a line feed is encountered.
|
Read from file until end-of-file or a line feed is encountered.
|
||||||
|
|
||||||
|
@ -84,9 +79,8 @@ void rdline_init(rdline_t *t, int fd, const char *filename,
|
||||||
outside the bounds set by argc, processing fails. On success,
|
outside the bounds set by argc, processing fails. On success,
|
||||||
the argv value is inserted and processed as described above.
|
the argv value is inserted and processed as described above.
|
||||||
- A '%' character can be escaped by writing '%%' or, if inside
|
- A '%' character can be escaped by writing '%%' or, if inside
|
||||||
a double quite string, by writing \%.
|
a double quoted string, by writing \%.
|
||||||
- An attempt to use such an indexed argument inside an argument
|
- Arguments are pasted as is. Substitution is not recursive.
|
||||||
expansion, results in failure.
|
|
||||||
- If the resulting line is empty, processing is restarted.
|
- If the resulting line is empty, processing is restarted.
|
||||||
*/
|
*/
|
||||||
int rdline(rdline_t *t);
|
int rdline(rdline_t *t);
|
||||||
|
@ -110,15 +104,6 @@ int unescape(char *src);
|
||||||
*/
|
*/
|
||||||
int pack_argv(char *str);
|
int pack_argv(char *str);
|
||||||
|
|
||||||
/*
|
|
||||||
Split the current input line into a space seperted keyword
|
|
||||||
(alphabetical characters only) and a value (the rest of the line).
|
|
||||||
|
|
||||||
If errors are encounted, prints a diagnostic message to stderr and
|
|
||||||
returns -1. On success, zero is returned.
|
|
||||||
*/
|
|
||||||
int splitkv(rdline_t *rd, char **k, char **v);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Parse a configuration file containing '<keyword> [arguments...]' lines.
|
Parse a configuration file containing '<keyword> [arguments...]' lines.
|
||||||
The cfgobj and flags are passed to the callback in the params array.
|
The cfgobj and flags are passed to the callback in the params array.
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
static const cfg_param_t *find_param(rdline_t *rd, const char *name,
|
static const cfg_param_t *find_param(rdline_t *rd, const char *name,
|
||||||
const cfg_param_t *params, size_t count)
|
const cfg_param_t *params, size_t count)
|
||||||
|
@ -35,6 +36,33 @@ static const cfg_param_t *find_param(rdline_t *rd, const char *name,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int splitkv(rdline_t *rd, char **k, char **v)
|
||||||
|
{
|
||||||
|
char *key = rd->line, *value = rd->line;
|
||||||
|
|
||||||
|
while (*value != ' ' && *value != '\0') {
|
||||||
|
if (!isalpha(*value)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: %zu: unexpected '%c' in keyword\n",
|
||||||
|
rd->filename, rd->lineno, *value);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
++value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*value != ' ') {
|
||||||
|
fprintf(stderr, "%s: %zu: expected argument after '%s'\n",
|
||||||
|
rd->filename, rd->lineno, key);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(value++) = '\0';
|
||||||
|
|
||||||
|
*k = key;
|
||||||
|
*v = value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
|
int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
|
@ -61,9 +89,9 @@ int rdcfg(void *cfgobj, rdline_t *rd, const cfg_param_t *params, size_t count,
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ret = rdline(rd)) == 0) {
|
while ((ret = rdline(rd)) == 0) {
|
||||||
if (strcmp(rd->buffer, "}") == 0)
|
if (strcmp(rd->line, "}") == 0)
|
||||||
break;
|
break;
|
||||||
if (p->handle(cfgobj, rd->buffer, rd, flags))
|
if (p->handle(cfgobj, rd->line, rd, flags))
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,151 +24,144 @@
|
||||||
|
|
||||||
#include "libcfg.h"
|
#include "libcfg.h"
|
||||||
|
|
||||||
static int rdline_getc(rdline_t *t)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
if (t->argstr != NULL) {
|
|
||||||
c = *(t->argstr++);
|
|
||||||
if (c != '\0')
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
t->argstr = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = read(t->fd, &c, 1);
|
|
||||||
} while (ret < 0 && errno == EINTR);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
if (t->i == 0) {
|
|
||||||
errno = 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
c = '\0';
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
return (c == '\n') ? '\0' : c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rdline_append(rdline_t *t, int c)
|
|
||||||
{
|
|
||||||
if (t->comment) {
|
|
||||||
if (c != '\0')
|
|
||||||
return 0;
|
|
||||||
} else if (t->string) {
|
|
||||||
if (t->escape) {
|
|
||||||
t->escape = false;
|
|
||||||
} else {
|
|
||||||
if (c == '\\')
|
|
||||||
t->escape = true;
|
|
||||||
if (c == '"')
|
|
||||||
t->string = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isspace(c))
|
|
||||||
c = ' ';
|
|
||||||
if (c == ' ' && (t->i == 0 || t->buffer[t->i - 1] == ' '))
|
|
||||||
return 0;
|
|
||||||
if (c == '#') {
|
|
||||||
t->comment = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (c == '"')
|
|
||||||
t->string = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '\0') {
|
|
||||||
while (t->i > 0 && t->buffer[t->i - 1] == ' ')
|
|
||||||
t->i -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t->i == sizeof(t->buffer))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
t->buffer[t->i++] = c;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rdline_init(rdline_t *t, int fd, const char *filename,
|
void rdline_init(rdline_t *t, int fd, const char *filename,
|
||||||
int argc, const char *const *argv)
|
int argc, const char *const *argv)
|
||||||
{
|
{
|
||||||
memset(t, 0, sizeof(*t));
|
memset(t, 0, sizeof(*t));
|
||||||
t->fd = fd;
|
t->fp = fdopen(fd, "r");
|
||||||
t->filename = filename;
|
t->filename = filename;
|
||||||
t->argc = argc;
|
t->argc = argc;
|
||||||
t->argv = argv;
|
t->argv = argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rdline(rdline_t *t)
|
void rdline_cleanup(rdline_t *t)
|
||||||
{
|
{
|
||||||
const char *errstr;
|
free(t->line);
|
||||||
int c;
|
fclose(t->fp);
|
||||||
retry:
|
}
|
||||||
t->i = 0;
|
|
||||||
t->argstr = NULL;
|
static int read_raw_line(rdline_t *t)
|
||||||
t->string = t->escape = t->comment = false;
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
free(t->line);
|
||||||
|
t->line = NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if (getline(&t->line, &len, t->fp) < 0) {
|
||||||
|
if (errno) {
|
||||||
|
fprintf(stderr, "%s: %zu: %s\n", t->filename,
|
||||||
|
t->lineno, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
t->lineno += 1;
|
t->lineno += 1;
|
||||||
|
|
||||||
do {
|
|
||||||
errno = 0;
|
|
||||||
c = rdline_getc(t);
|
|
||||||
if (c < 0) {
|
|
||||||
if (errno == 0)
|
|
||||||
return 1;
|
|
||||||
errstr = strerror(errno);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (c == 0 && t->string) {
|
|
||||||
errstr = "missing \"";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == '%') {
|
|
||||||
c = rdline_getc(t);
|
|
||||||
if (c == 0) {
|
|
||||||
errstr = "unexpected end of line after '%%'";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (c < 0) {
|
|
||||||
errstr = strerror(errno);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c != '%') {
|
|
||||||
if (!isdigit(c)) {
|
|
||||||
errstr = "exptected digit after '%%'";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if ((c - '0') >= t->argc) {
|
|
||||||
errstr = "argument out of range";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (t->argstr != NULL) {
|
|
||||||
errstr = "recursive argument "
|
|
||||||
"expansion";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
t->argstr = t->argv[c - '0'];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rdline_append(t, c)) {
|
|
||||||
errstr = "line too long";
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
} while (c != '\0');
|
|
||||||
|
|
||||||
if (t->buffer[0] == '\0')
|
|
||||||
goto retry;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int normalize_line(rdline_t *t)
|
||||||
|
{
|
||||||
|
char *dst = t->line, *src = t->line;
|
||||||
|
bool string = false;
|
||||||
|
const char *errstr;
|
||||||
|
int c, ret = 0;
|
||||||
|
|
||||||
|
while (isspace(*src))
|
||||||
|
++src;
|
||||||
|
|
||||||
|
while (*src != '\0' && (string || *src != '#')) {
|
||||||
|
c = *(src++);
|
||||||
|
|
||||||
|
if (c == '"') {
|
||||||
|
string = !string;
|
||||||
|
} else if (!string && isspace(c)) {
|
||||||
|
c = ' ';
|
||||||
|
if (dst > t->line && dst[-1] == ' ')
|
||||||
|
continue;
|
||||||
|
} else if (c == '%') {
|
||||||
|
*(dst++) = c;
|
||||||
|
c = *(src++);
|
||||||
|
if (c != '%' && !isdigit(c)) {
|
||||||
|
errstr = "expected digit after '%%'";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (isdigit(c) && (c - '0') >= t->argc) {
|
||||||
|
errstr = "argument out of range";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
ret += strlen(t->argv[c - '0']);
|
||||||
|
} else if (string && c == '\\' && *src != '\0') {
|
||||||
|
*(dst++) = c;
|
||||||
|
c = *(src++);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(dst++) = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string) {
|
||||||
|
errstr = "missing \"";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (dst > t->line && dst[-1] == ' ')
|
||||||
|
--dst;
|
||||||
|
*dst = '\0';
|
||||||
|
return ret;
|
||||||
fail:
|
fail:
|
||||||
fprintf(stderr, "%s: %zu: %s\n", t->filename, t->lineno, errstr);
|
fprintf(stderr, "%s: %zu: %s\n", t->filename, t->lineno, errstr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void substitute(rdline_t *t, char *dst, char *src)
|
||||||
|
{
|
||||||
|
bool string = false;
|
||||||
|
|
||||||
|
while (*src != '\0') {
|
||||||
|
if (src[0] == '%' && isdigit(src[1])) {
|
||||||
|
strcpy(dst, t->argv[src[1] - '0']);
|
||||||
|
src += 2;
|
||||||
|
while (*dst != '\0')
|
||||||
|
++dst;
|
||||||
|
} else {
|
||||||
|
if (*src == '"')
|
||||||
|
string = !string;
|
||||||
|
if (string && *src == '\\')
|
||||||
|
*(dst++) = *(src++);
|
||||||
|
*(dst++) = *(src++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rdline(rdline_t *t)
|
||||||
|
{
|
||||||
|
char *buffer = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((ret = read_raw_line(t)))
|
||||||
|
goto out;
|
||||||
|
if ((ret = normalize_line(t)) < 0)
|
||||||
|
goto out;
|
||||||
|
} while (t->line[0] == '\0');
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
buffer = calloc(1, strlen(t->line) + ret + 1);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
fprintf(stderr, "%s: %zu: out of memory\n",
|
||||||
|
t->filename, t->lineno);
|
||||||
|
ret = -1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
substitute(t, buffer, t->line);
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
|
free(t->line);
|
||||||
|
t->line = buffer;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2018 - David Oberhollenzer
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "libcfg.h"
|
|
||||||
|
|
||||||
int splitkv(rdline_t *rd, char **k, char **v)
|
|
||||||
{
|
|
||||||
char *key = rd->buffer, *value = rd->buffer;
|
|
||||||
|
|
||||||
while (*value != ' ' && *value != '\0') {
|
|
||||||
if (!isalpha(*value)) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s: %zu: unexpected '%c' in keyword\n",
|
|
||||||
rd->filename, rd->lineno, *value);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
++value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*value != ' ') {
|
|
||||||
fprintf(stderr, "%s: %zu: expected argument after '%s'\n",
|
|
||||||
rd->filename, rd->lineno, key);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*(value++) = '\0';
|
|
||||||
|
|
||||||
*k = key;
|
|
||||||
*v = value;
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -266,8 +266,6 @@ service_t *rdsvc(int dirfd, const char *filename, int flags)
|
||||||
argc = 0;
|
argc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdline_init(&rd, fd, filename, argc, args);
|
|
||||||
|
|
||||||
nlen = (arg != NULL) ? (size_t)(arg - filename) : strlen(filename);
|
nlen = (arg != NULL) ? (size_t)(arg - filename) : strlen(filename);
|
||||||
|
|
||||||
svc = calloc(1, sizeof(*svc) + nlen + 1);
|
svc = calloc(1, sizeof(*svc) + nlen + 1);
|
||||||
|
@ -282,14 +280,17 @@ service_t *rdsvc(int dirfd, const char *filename, int flags)
|
||||||
|
|
||||||
memcpy(svc->name, filename, nlen);
|
memcpy(svc->name, filename, nlen);
|
||||||
|
|
||||||
if (rdcfg(svc, &rd, svc_params, ARRAY_SIZE(svc_params), flags))
|
rdline_init(&rd, fd, filename, argc, args);
|
||||||
goto fail;
|
|
||||||
|
|
||||||
close(fd);
|
if (rdcfg(svc, &rd, svc_params, ARRAY_SIZE(svc_params), flags)) {
|
||||||
|
delsvc(svc);
|
||||||
|
svc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rdline_cleanup(&rd);
|
||||||
return svc;
|
return svc;
|
||||||
fail_oom:
|
fail_oom:
|
||||||
fputs("out of memory\n", stderr);
|
fputs("out of memory\n", stderr);
|
||||||
fail:
|
|
||||||
delsvc(svc);
|
delsvc(svc);
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in a new issue