diff options
| author | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-04-08 13:30:20 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-04-08 14:05:39 +0200 | 
| commit | 7d8ceb810faa085650d2d74e3d1c857b8b755ca3 (patch) | |
| tree | cf58443a3df0c52be479648ffccd13f6d23fc403 /lib/src | |
| parent | b81668e045b6a2105b7b0b9e2e5afa8e631e6ec5 (diff) | |
Cleanup: split rdsvc into multiple functions
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
Diffstat (limited to 'lib/src')
| -rw-r--r-- | lib/src/delsvc.c | 3 | ||||
| -rw-r--r-- | lib/src/rdsvc.c | 194 | 
2 files changed, 108 insertions, 89 deletions
| diff --git a/lib/src/delsvc.c b/lib/src/delsvc.c index 7370653..968aa0d 100644 --- a/lib/src/delsvc.c +++ b/lib/src/delsvc.c @@ -23,6 +23,9 @@ void delsvc(service_t *svc)  {  	exec_t *e; +	if (svc == NULL) +		return; +  	while (svc->exec != NULL) {  		e = svc->exec;  		svc->exec = e->next; diff --git a/lib/src/rdsvc.c b/lib/src/rdsvc.c index 5058c76..8e9603d 100644 --- a/lib/src/rdsvc.c +++ b/lib/src/rdsvc.c @@ -220,7 +220,7 @@ static int svc_target(service_t *svc, char *arg,  	return 0;  } -static const struct { +static const struct svc_param {  	const char *key;  	int (*handle)(service_t *svc, char *arg, @@ -236,12 +236,97 @@ static const struct {  }; +static char *get_line(int fd, const char *filename, size_t *lineno, +		      int argc, const char *const *args) +{ +	const char *error; +	char *line; +	int ret; +retry: +	errno = 0; +	line = rdline(fd, argc, args); +	ret = errno; + +	if (line == NULL && errno != 0) { +		switch (errno) { +		case EINVAL: error = "error in argument expansion";  break; +		case ELOOP:  error = "recursive argument expansion"; break; +		case EILSEQ: error = "missing \"";                   break; +		default:     error = strerror(errno);                break; +		} + +		fprintf(stderr, "%s: %zu: %s\n", filename, *lineno, error); +	} + +	if (line != NULL && strlen(line) == 0) { +		free(line); +		(*lineno) += 1; +		goto retry; +	} + +	errno = ret; +	return line; +} + +static int splitkv(const char *filename, size_t lineno, +		   char *line, char **k, char **v) +{ +	char *key = line, *value = line; + +	*k = *v = NULL; + +	while (*value != ' ' && *value != '\0') { +		if (!isalpha(*value)) { +			fprintf(stderr, +				"%s: %zu: unexpected '%c' in keyword\n", +				filename, lineno, *value); +			return -1; +		} +		++value; +	} + +	if (*value != ' ') { +		fprintf(stderr, "%s: %zu: expected argument after '%s'\n", +			filename, lineno, key); +		return -1; +	} + +	*(value++) = '\0'; + +	value = strdup(value); +	if (value == NULL) { +		fprintf(stderr, "%s: %zu: out of memory\n", filename, lineno); +		return -1; +	} + +	*k = key; +	*v = value; +	return 0; +} + +static const struct svc_param *find_param(const char *filename, size_t lineno, +					  const char *name) +{ +	size_t i; + +	for (i = 0; i < ARRAY_SIZE(svc_params); ++i) { +		if (!strcmp(svc_params[i].key, name)) +			return svc_params + i; +	} + +	fprintf(stderr, "%s: %zu: unknown keyword '%s'\n", +		filename, lineno, name); +	return NULL; +} + +  service_t *rdsvc(int dirfd, const char *filename)  { -	const char *arg, *args[1], *error; -	char *line, *key, *value; -	size_t i, argc, lineno; -	service_t *svc; +	char *line = NULL, *key, *value = NULL; +	const struct svc_param *p; +	const char *arg, *args[1]; +	service_t *svc = NULL; +	size_t argc, lineno;  	int fd;  	fd = openat(dirfd, filename, O_RDONLY); @@ -259,11 +344,8 @@ service_t *rdsvc(int dirfd, const char *filename)  	}  	svc = calloc(1, sizeof(*svc)); -	if (svc == NULL) { -		fputs("out of memory\n", stderr); -		close(fd); -		return NULL; -	} +	if (svc == NULL) +		goto fail_oom;  	if (arg != NULL) {  		svc->name = strndup(filename, arg - filename); @@ -271,101 +353,35 @@ service_t *rdsvc(int dirfd, const char *filename)  		svc->name = strdup(filename);  	} -	if (svc->name == NULL) { -		free(svc); -		fputs("out of memory\n", stderr); -		close(fd); -		return NULL; -	} +	if (svc->name == NULL) +		goto fail_oom;  	for (lineno = 1; ; ++lineno) { -		errno = 0; -		line = rdline(fd, argc, args); - +		line = get_line(fd, filename, &lineno, argc, args);  		if (line == NULL) {  			if (errno == 0)  				break; - -			switch (errno) { -			case EINVAL: -				error = "error in argument expansion"; -				break; -			case ELOOP: -				error = "recursive argument expansion"; -				break; -			case EILSEQ: -				error = "missing \""; -				break; -			default: -				error = strerror(errno); -				break; -			} - -			fprintf(stderr, "%s: %zu: %s\n", -				filename, lineno, error);  			goto fail;  		} -		if (!strlen(line)) { -			free(line); -			continue; -		} - -		key = value = line; - -		while (*value != ' ' && *value != '\0') { -			if (!isalpha(*value)) { -				fprintf(stderr, "%s: %zu: unexpected '%c' in " -					"keyword\n", filename, lineno, *value); -				goto fail_line; -			} -			++value; -		} - -		if (*value == ' ') { -			*(value++) = '\0'; -		} else { -			value = NULL; -		} - -		for (i = 0; i < ARRAY_SIZE(svc_params); ++i) { -			if (!strcmp(svc_params[i].key, key)) -				break; -		} - -		if (i >= ARRAY_SIZE(svc_params)) { -			fprintf(stderr, "%s: %zu: unknown keyword '%s'\n", -				filename, lineno, key); -			goto fail_line; -		} - -		if (value == NULL) { -			fprintf(stderr, -				"%s: %zu: expected argument after '%s'\n", -				filename, lineno, key); -			goto fail_line; -		} - -		value = strdup(value); -		if (value == NULL) { -			fputs("out of memory", stderr); -			goto fail_line; -		} +		if (splitkv(filename, lineno, line, &key, &value)) +			goto fail; -		if (svc_params[i].handle(svc, value, filename, lineno)) { -			free(value); -			goto fail_line; -		} +		p = find_param(filename, lineno, key); +		if (p == NULL || p->handle(svc, value, filename, lineno) != 0) +			goto fail;  		free(line);  	}  	close(fd);  	return svc; -fail_line: -	free(line); +fail_oom: +	fputs("out of memory\n", stderr);  fail: -	close(fd); +	free(value); +	free(line);  	delsvc(svc); +	close(fd);  	return NULL;  } | 
