cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob f180af14e3a3264abae8a13f01a8ba17f394f44b 3910 bytes (raw)
$ git show HEAD:cfg_parser.rl	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
 
/*
 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
 */
/*
 * parses config files used by the original (Perl) mogstored
 */
#include "cmogstored.h"
#include "cfg.h"
#include "listen_parser.h"

static char *mystrdup(const char *key, char *mark_beg, const char *p)
{
	size_t mark_len = p - mark_beg;
	mark_beg[mark_len] = 0;
	if (strlen(mark_beg) != mark_len) {
		syslog(LOG_ERR, "NUL character in `%s' value", key);
		return NULL;
	}

	return xstrdup(mark_beg);
}

%%{
	machine cfg_parser;
	include listen_parser_common "listen_parser_common.rl";

	eor = '\n';
	ignored_line := ( (any-'\n')* eor ) @ { fgoto main; };
	lws = (space-'\n');
	comment = lws* ("#"(any-'\n')*);
	comment_line = comment eor;
	sep = lws* "=" lws*;

	path = ((any - space)+) > { mark_beg = fpc; };

	mgmtlisten = lws* "mgmtlisten" sep listen comment* (eor) > {
		a = mog_listen_parse_internal(mark_beg, mark_len,
		                              port_beg, port_len, sa_family);
		if (!a) return -1;
		cfg->mgmtlisten = a;
	};

	httplisten = lws* "httplisten" sep listen comment* eor > {
		a = mog_listen_parse_internal(mark_beg, mark_len,
		                              port_beg, port_len, sa_family);
		if (!a) return -1;
		cfg->httplisten = a;
	};
	httpgetlisten = lws* "httpgetlisten" sep listen comment* eor > {
		a = mog_listen_parse_internal(mark_beg, mark_len,
		                              port_beg, port_len, sa_family);
		if (!a) return -1;
		cfg->httpgetlisten = a;
	};
	docroot = lws* "docroot" sep path (comment* eor) > {
		/* delay realpath(3) until svc init, symlinks may change */
		cfg->docroot = mystrdup("docroot", mark_beg, fpc);
		if (!cfg->docroot) return -1;
	};
	pidfile = lws* "pidfile" sep path (comment* eor) > {
		/* delay realpath(3) until svc init, symlinks may change */
		cfg->pidfile = mystrdup("pidfile", mark_beg, fpc);
		if (!cfg->pidfile) return -1;
	};
	daemonize_compat = lws* "daemonize" comment* eor > {
		syslog(LOG_ERR,
"\"daemonize\" in was supported in error in the past and now deprecated");
		syslog(LOG_ERR,
"use \"daemonize = 1\" in your config file instead");
		cfg->daemonize = true;
	};
	daemonize = lws* "daemonize" sep
		((any - space)+) > { mark_beg = fpc; }
		(comment* eor) > {
			mark_len = fpc - mark_beg;
			mark_beg[mark_len] = 0;

			/* special case for compatibility with mogstored */
			cfg->daemonize = strcmp("0", mark_beg);
		};
	maxconns = lws* "maxconns" sep
		(digit+) > { mark_beg = fpc; }
		(comment* eor) > {
			mark_len = fpc - mark_beg;
			mark_beg[mark_len] = 0;
			errno = 0;
			cfg->maxconns = strtoul(mark_beg, NULL, 10);
			if (errno) {
				syslog(LOG_ERR,
				       "failed to parse: maxconns = %s - %m",
				       mark_beg);
				return -1;
			}
		};
	server = lws* "server" sep
		(alpha+) > { mark_beg = fpc; }
		(comment* eor) > {
			cfg->server = mystrdup("server", mark_beg, fpc);
			if (!cfg->server) return -1;
			mog_cfg_check_server(cfg);
		};
	serverbin = lws* "serverbin" sep path
		(comment* eor) > {
			char *tmp = mystrdup("serverbin", mark_beg, fpc);
			if (!tmp) return -1;
			warn("W: serverbin = %s ignored", tmp);
			free(tmp);
		};
	main := (mgmtlisten | httplisten | httpgetlisten |
	         pidfile | docroot | daemonize | daemonize_compat | maxconns |
		 server | serverbin ) +
		$! {
			fhold;
			fgoto ignored_line;
		};
}%%

%% write data;

/* this is a one-shot parser, no need to stream local config files  */
int mog_cfg_parse(struct mog_cfg *cfg, char *buf, size_t len)
{
	char *p, *pe, *eof = NULL;
	char *mark_beg = NULL;
	char *port_beg = NULL;
	size_t mark_len = 0;
	size_t port_len = 0;
	sa_family_t sa_family = AF_INET;
	struct mog_addrinfo *a;
	int cs;

	%% write init;

	p = buf;
	pe = buf + len;

	%% write exec;

	if (cs == cfg_parser_error)
		return -1;

	assert(p <= pe && "buffer overflow after cfg parse");
	return 0;
}

git clone https://yhbt.net/cmogstored.git