Blame


1 b0a6bcf7 2022-09-13 op /*
2 b0a6bcf7 2022-09-13 op * Copyright (c) 2022 Omar Polo <op@omarpolo.com>
3 b0a6bcf7 2022-09-13 op * Copyright (c) 2007-2016 Reyk Floeter <reyk@openbsd.org>
4 b0a6bcf7 2022-09-13 op * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
5 b0a6bcf7 2022-09-13 op * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
6 b0a6bcf7 2022-09-13 op * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
7 b0a6bcf7 2022-09-13 op * Copyright (c) 2001 Markus Friedl. All rights reserved.
8 b0a6bcf7 2022-09-13 op * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
9 b0a6bcf7 2022-09-13 op * Copyright (c) 2001 Theo de Raadt. All rights reserved.
10 b0a6bcf7 2022-09-13 op *
11 b0a6bcf7 2022-09-13 op * Permission to use, copy, modify, and distribute this software for any
12 b0a6bcf7 2022-09-13 op * purpose with or without fee is hereby granted, provided that the above
13 b0a6bcf7 2022-09-13 op * copyright notice and this permission notice appear in all copies.
14 b0a6bcf7 2022-09-13 op *
15 b0a6bcf7 2022-09-13 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 b0a6bcf7 2022-09-13 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 b0a6bcf7 2022-09-13 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 b0a6bcf7 2022-09-13 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 b0a6bcf7 2022-09-13 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 b0a6bcf7 2022-09-13 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 b0a6bcf7 2022-09-13 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 b0a6bcf7 2022-09-13 op */
23 b0a6bcf7 2022-09-13 op
24 b0a6bcf7 2022-09-13 op %{
25 b0a6bcf7 2022-09-13 op #include <sys/types.h>
26 b0a6bcf7 2022-09-13 op #include <sys/queue.h>
27 b0a6bcf7 2022-09-13 op #include <sys/tree.h>
28 b0a6bcf7 2022-09-13 op #include <sys/uio.h>
29 b0a6bcf7 2022-09-13 op
30 b0a6bcf7 2022-09-13 op #include <err.h>
31 b0a6bcf7 2022-09-13 op #include <event.h>
32 b0a6bcf7 2022-09-13 op #include <netdb.h>
33 b0a6bcf7 2022-09-13 op #include <stdio.h>
34 b0a6bcf7 2022-09-13 op #include <stdlib.h>
35 b0a6bcf7 2022-09-13 op #include <limits.h>
36 b0a6bcf7 2022-09-13 op #include <stdarg.h>
37 b0a6bcf7 2022-09-13 op #include <stdint.h>
38 b0a6bcf7 2022-09-13 op #include <string.h>
39 b0a6bcf7 2022-09-13 op #include <unistd.h>
40 b0a6bcf7 2022-09-13 op #include <ctype.h>
41 b0a6bcf7 2022-09-13 op #include <errno.h>
42 b0a6bcf7 2022-09-13 op #include <fcntl.h>
43 b0a6bcf7 2022-09-13 op #include <pwd.h>
44 b0a6bcf7 2022-09-13 op #include <imsg.h>
45 b0a6bcf7 2022-09-13 op
46 b0a6bcf7 2022-09-13 op #include "log.h"
47 b0a6bcf7 2022-09-13 op #include "proc.h"
48 b0a6bcf7 2022-09-13 op
49 b0a6bcf7 2022-09-13 op #include "galileo.h"
50 b0a6bcf7 2022-09-13 op
51 b0a6bcf7 2022-09-13 op TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
52 b0a6bcf7 2022-09-13 op static struct file {
53 b0a6bcf7 2022-09-13 op TAILQ_ENTRY(file) entry;
54 b0a6bcf7 2022-09-13 op FILE *stream;
55 b0a6bcf7 2022-09-13 op char *name;
56 b0a6bcf7 2022-09-13 op size_t ungetpos;
57 b0a6bcf7 2022-09-13 op size_t ungetsize;
58 b0a6bcf7 2022-09-13 op u_char *ungetbuf;
59 b0a6bcf7 2022-09-13 op int eof_reached;
60 b0a6bcf7 2022-09-13 op int lineno;
61 b0a6bcf7 2022-09-13 op int errors;
62 b0a6bcf7 2022-09-13 op } *file, *topfile;
63 b0a6bcf7 2022-09-13 op struct file *pushfile(const char *, int);
64 b0a6bcf7 2022-09-13 op int popfile(void);
65 b0a6bcf7 2022-09-13 op int yyparse(void);
66 b0a6bcf7 2022-09-13 op int yylex(void);
67 b0a6bcf7 2022-09-13 op int yyerror(const char *, ...)
68 b0a6bcf7 2022-09-13 op __attribute__((__format__ (printf, 1, 2)))
69 b0a6bcf7 2022-09-13 op __attribute__((__nonnull__ (1)));
70 b0a6bcf7 2022-09-13 op int kw_cmp(const void *, const void *);
71 b0a6bcf7 2022-09-13 op int lookup(char *);
72 b0a6bcf7 2022-09-13 op int igetc(void);
73 b0a6bcf7 2022-09-13 op int lgetc(int);
74 b0a6bcf7 2022-09-13 op void lungetc(int);
75 b0a6bcf7 2022-09-13 op int findeol(void);
76 b0a6bcf7 2022-09-13 op
77 b0a6bcf7 2022-09-13 op TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
78 b0a6bcf7 2022-09-13 op struct sym {
79 b0a6bcf7 2022-09-13 op TAILQ_ENTRY(sym) entry;
80 b0a6bcf7 2022-09-13 op int used;
81 b0a6bcf7 2022-09-13 op int persist;
82 b0a6bcf7 2022-09-13 op char *nam;
83 b0a6bcf7 2022-09-13 op char *val;
84 b0a6bcf7 2022-09-13 op };
85 b0a6bcf7 2022-09-13 op int symset(const char *, const char *, int);
86 b0a6bcf7 2022-09-13 op char *symget(const char *);
87 b0a6bcf7 2022-09-13 op
88 b0a6bcf7 2022-09-13 op int getservice(const char *);
89 b0a6bcf7 2022-09-13 op
90 b0a6bcf7 2022-09-13 op static struct galileo *conf = NULL;
91 b0a6bcf7 2022-09-13 op static struct server *srv = NULL;
92 b0a6bcf7 2022-09-13 op static int errors;
93 b0a6bcf7 2022-09-13 op
94 b0a6bcf7 2022-09-13 op typedef struct {
95 b0a6bcf7 2022-09-13 op union {
96 b0a6bcf7 2022-09-13 op int64_t number;
97 b0a6bcf7 2022-09-13 op char *string;
98 b0a6bcf7 2022-09-13 op } v;
99 b0a6bcf7 2022-09-13 op int lineno;
100 b0a6bcf7 2022-09-13 op } YYSTYPE;
101 b0a6bcf7 2022-09-13 op
102 b0a6bcf7 2022-09-13 op %}
103 b0a6bcf7 2022-09-13 op
104 b0a6bcf7 2022-09-13 op %token INCLUDE ERROR
105 b0a6bcf7 2022-09-13 op %token CHROOT HOSTNAME PORT PREFORK PROXY SERVER SOURCE STYLESHEET
106 b0a6bcf7 2022-09-13 op %type <v.number> NUMBER
107 b0a6bcf7 2022-09-13 op %type <v.number> port
108 b0a6bcf7 2022-09-13 op %type <v.string> STRING
109 b0a6bcf7 2022-09-13 op %type <v.string> string
110 b0a6bcf7 2022-09-13 op
111 b0a6bcf7 2022-09-13 op %%
112 b0a6bcf7 2022-09-13 op
113 b0a6bcf7 2022-09-13 op grammar : /* empty */
114 b0a6bcf7 2022-09-13 op | grammar include '\n'
115 b0a6bcf7 2022-09-13 op | grammar '\n'
116 b0a6bcf7 2022-09-13 op | grammar varset '\n'
117 b0a6bcf7 2022-09-13 op | grammar main '\n'
118 b0a6bcf7 2022-09-13 op | grammar server '\n'
119 b0a6bcf7 2022-09-13 op | grammar error '\n' { file->errors++; }
120 b0a6bcf7 2022-09-13 op ;
121 b0a6bcf7 2022-09-13 op
122 b0a6bcf7 2022-09-13 op include : INCLUDE string {
123 b0a6bcf7 2022-09-13 op struct file *nfile;
124 b0a6bcf7 2022-09-13 op
125 b0a6bcf7 2022-09-13 op if ((nfile = pushfile($2, 0)) == NULL) {
126 b0a6bcf7 2022-09-13 op yyerror("failed to include file %s", $2);
127 b0a6bcf7 2022-09-13 op free($2);
128 b0a6bcf7 2022-09-13 op YYERROR;
129 b0a6bcf7 2022-09-13 op }
130 b0a6bcf7 2022-09-13 op free($2);
131 b0a6bcf7 2022-09-13 op
132 b0a6bcf7 2022-09-13 op file = nfile;
133 b0a6bcf7 2022-09-13 op lungetc('\n');
134 b0a6bcf7 2022-09-13 op }
135 b0a6bcf7 2022-09-13 op ;
136 b0a6bcf7 2022-09-13 op
137 b0a6bcf7 2022-09-13 op varset : STRING '=' STRING {
138 b0a6bcf7 2022-09-13 op char *s = $1;
139 b0a6bcf7 2022-09-13 op while (*s++) {
140 b0a6bcf7 2022-09-13 op if (isspace((unsigned char)*s)) {
141 b0a6bcf7 2022-09-13 op yyerror("macro name cannot contain "
142 b0a6bcf7 2022-09-13 op "whitespace");
143 b0a6bcf7 2022-09-13 op free($1);
144 b0a6bcf7 2022-09-13 op free($3);
145 b0a6bcf7 2022-09-13 op YYERROR;
146 b0a6bcf7 2022-09-13 op }
147 b0a6bcf7 2022-09-13 op }
148 b0a6bcf7 2022-09-13 op if (symset($1, $3, 0) == -1)
149 b0a6bcf7 2022-09-13 op fatalx("cannot store variable");
150 b0a6bcf7 2022-09-13 op free($1);
151 b0a6bcf7 2022-09-13 op free($3);
152 b0a6bcf7 2022-09-13 op }
153 b0a6bcf7 2022-09-13 op ;
154 b0a6bcf7 2022-09-13 op
155 b0a6bcf7 2022-09-13 op main : PREFORK NUMBER {
156 b0a6bcf7 2022-09-13 op if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
157 b0a6bcf7 2022-09-13 op yyerror("invalid number of preforked "
158 b0a6bcf7 2022-09-13 op "servers: %lld", $2);
159 b0a6bcf7 2022-09-13 op YYERROR;
160 b0a6bcf7 2022-09-13 op }
161 b0a6bcf7 2022-09-13 op conf->sc_prefork = $2;
162 b0a6bcf7 2022-09-13 op }
163 b0a6bcf7 2022-09-13 op | CHROOT STRING {
164 b0a6bcf7 2022-09-13 op size_t n;
165 b0a6bcf7 2022-09-13 op
166 b0a6bcf7 2022-09-13 op n = strlcpy(conf->sc_chroot, $2,
167 b0a6bcf7 2022-09-13 op sizeof(conf->sc_chroot));
168 b0a6bcf7 2022-09-13 op if (n >= sizeof(conf->sc_chroot))
169 b0a6bcf7 2022-09-13 op yyerror("chroot path too long!");
170 b0a6bcf7 2022-09-13 op free($2);
171 b0a6bcf7 2022-09-13 op }
172 b0a6bcf7 2022-09-13 op ;
173 b0a6bcf7 2022-09-13 op
174 b0a6bcf7 2022-09-13 op server : SERVER STRING {
175 b0a6bcf7 2022-09-13 op struct server *s;
176 b0a6bcf7 2022-09-13 op size_t n;
177 b0a6bcf7 2022-09-13 op
178 b0a6bcf7 2022-09-13 op if ((s = calloc(1, sizeof(*s))) == NULL)
179 b0a6bcf7 2022-09-13 op fatal("calloc");
180 b0a6bcf7 2022-09-13 op
181 b0a6bcf7 2022-09-13 op n = strlcpy(s->srv_conf.host, $2,
182 b0a6bcf7 2022-09-13 op sizeof(s->srv_conf.host));
183 b0a6bcf7 2022-09-13 op if (n >= sizeof(s->srv_conf.host)) {
184 b0a6bcf7 2022-09-13 op yyerror("server name too long");
185 b0a6bcf7 2022-09-13 op free($2);
186 b0a6bcf7 2022-09-13 op free(s);
187 b0a6bcf7 2022-09-13 op YYERROR;
188 b0a6bcf7 2022-09-13 op }
189 b0a6bcf7 2022-09-13 op free($2);
190 b0a6bcf7 2022-09-13 op
191 b0a6bcf7 2022-09-13 op srv = s;
192 b0a6bcf7 2022-09-13 op TAILQ_INSERT_TAIL(&conf->sc_servers, srv, srv_entry);
193 b0a6bcf7 2022-09-13 op } '{' optnl serveropts_l '}' {
194 b0a6bcf7 2022-09-13 op /* check if duplicate */
195 b0a6bcf7 2022-09-13 op /* eventually load the tls certs */
196 b0a6bcf7 2022-09-13 op
197 b0a6bcf7 2022-09-13 op srv = NULL;
198 b0a6bcf7 2022-09-13 op }
199 b0a6bcf7 2022-09-13 op ;
200 b0a6bcf7 2022-09-13 op
201 b0a6bcf7 2022-09-13 op serveropts_l : serveropts_l serveroptsl nl
202 b0a6bcf7 2022-09-13 op | serveroptsl optnl
203 b0a6bcf7 2022-09-13 op ;
204 b0a6bcf7 2022-09-13 op
205 b0a6bcf7 2022-09-13 op serveroptsl : PROXY STRING {
206 b0a6bcf7 2022-09-13 op /* ... */
207 b0a6bcf7 2022-09-13 op }
208 b0a6bcf7 2022-09-13 op | PROXY '{' optnl proxyopts_l '}'
209 fc1cb9ea 2022-09-14 op | STYLESHEET string {
210 fc1cb9ea 2022-09-14 op size_t n;
211 fc1cb9ea 2022-09-14 op
212 fc1cb9ea 2022-09-14 op n = strlcpy(srv->srv_conf.stylesheet, $2,
213 fc1cb9ea 2022-09-14 op sizeof(srv->srv_conf.stylesheet));
214 fc1cb9ea 2022-09-14 op if (n >= sizeof(srv->srv_conf.stylesheet))
215 fc1cb9ea 2022-09-14 op yyerror("stylesheet path too long!");
216 fc1cb9ea 2022-09-14 op free($2);
217 fc1cb9ea 2022-09-14 op }
218 b0a6bcf7 2022-09-13 op ;
219 b0a6bcf7 2022-09-13 op
220 b0a6bcf7 2022-09-13 op proxyopts_l : proxyopts_l proxyoptsl nl
221 b0a6bcf7 2022-09-13 op | proxyoptsl optnl
222 b0a6bcf7 2022-09-13 op ;
223 b0a6bcf7 2022-09-13 op
224 b0a6bcf7 2022-09-13 op proxyoptsl : SOURCE STRING PORT port {
225 b0a6bcf7 2022-09-13 op size_t n;
226 b0a6bcf7 2022-09-13 op
227 b0a6bcf7 2022-09-13 op n = strlcpy(srv->srv_conf.proxy_addr, $2,
228 b0a6bcf7 2022-09-13 op sizeof(srv->srv_conf.proxy_addr));
229 b0a6bcf7 2022-09-13 op if (n >= sizeof(srv->srv_conf.proxy_addr))
230 b0a6bcf7 2022-09-13 op yyerror("proxy source too long!");
231 b0a6bcf7 2022-09-13 op srv->srv_conf.proxy_port = $4;
232 b0a6bcf7 2022-09-13 op
233 b0a6bcf7 2022-09-13 op free($2);
234 b0a6bcf7 2022-09-13 op }
235 b0a6bcf7 2022-09-13 op | HOSTNAME STRING {
236 b0a6bcf7 2022-09-13 op size_t n;
237 b0a6bcf7 2022-09-13 op
238 b0a6bcf7 2022-09-13 op n = strlcpy(srv->srv_conf.proxy_name, $2,
239 b0a6bcf7 2022-09-13 op sizeof(srv->srv_conf.proxy_name));
240 b0a6bcf7 2022-09-13 op if (n >= sizeof(srv->srv_conf.proxy_name))
241 b0a6bcf7 2022-09-13 op yyerror("proxy hostname too long!");
242 b0a6bcf7 2022-09-13 op free($2);
243 b0a6bcf7 2022-09-13 op }
244 b0a6bcf7 2022-09-13 op ;
245 b0a6bcf7 2022-09-13 op
246 b0a6bcf7 2022-09-13 op port : NUMBER {
247 b0a6bcf7 2022-09-13 op if ($1 <= 0 || $1 > (int)USHRT_MAX) {
248 b0a6bcf7 2022-09-13 op yyerror("invalid port: %lld", $1);
249 b0a6bcf7 2022-09-13 op YYERROR;
250 b0a6bcf7 2022-09-13 op }
251 b0a6bcf7 2022-09-13 op $$ = $1;
252 b0a6bcf7 2022-09-13 op }
253 b0a6bcf7 2022-09-13 op | STRING {
254 b0a6bcf7 2022-09-13 op int val;
255 b0a6bcf7 2022-09-13 op
256 b0a6bcf7 2022-09-13 op if ((val = getservice($1)) == -1) {
257 b0a6bcf7 2022-09-13 op yyerror("invalid port: %s", $1);
258 b0a6bcf7 2022-09-13 op free($1);
259 b0a6bcf7 2022-09-13 op YYERROR;
260 b0a6bcf7 2022-09-13 op }
261 b0a6bcf7 2022-09-13 op free($1);
262 b0a6bcf7 2022-09-13 op $$ = val;
263 b0a6bcf7 2022-09-13 op }
264 b0a6bcf7 2022-09-13 op ;
265 b0a6bcf7 2022-09-13 op
266 b0a6bcf7 2022-09-13 op string : STRING string {
267 b0a6bcf7 2022-09-13 op if (asprintf(&$$, "%s%s", $1, $2) == -1)
268 b0a6bcf7 2022-09-13 op fatal("asprintf string");
269 b0a6bcf7 2022-09-13 op free($1);
270 b0a6bcf7 2022-09-13 op free($2);
271 b0a6bcf7 2022-09-13 op }
272 b0a6bcf7 2022-09-13 op | STRING
273 b0a6bcf7 2022-09-13 op ;
274 b0a6bcf7 2022-09-13 op
275 b0a6bcf7 2022-09-13 op optnl : '\n' optnl
276 b0a6bcf7 2022-09-13 op |
277 b0a6bcf7 2022-09-13 op ;
278 b0a6bcf7 2022-09-13 op
279 b0a6bcf7 2022-09-13 op nl : '\n' optnl
280 b0a6bcf7 2022-09-13 op ;
281 b0a6bcf7 2022-09-13 op
282 b0a6bcf7 2022-09-13 op %%
283 b0a6bcf7 2022-09-13 op
284 b0a6bcf7 2022-09-13 op struct keywords {
285 b0a6bcf7 2022-09-13 op const char *k_name;
286 b0a6bcf7 2022-09-13 op int k_val;
287 b0a6bcf7 2022-09-13 op };
288 b0a6bcf7 2022-09-13 op
289 b0a6bcf7 2022-09-13 op int
290 b0a6bcf7 2022-09-13 op yyerror(const char *fmt, ...)
291 b0a6bcf7 2022-09-13 op {
292 b0a6bcf7 2022-09-13 op va_list ap;
293 b0a6bcf7 2022-09-13 op char *msg;
294 b0a6bcf7 2022-09-13 op
295 b0a6bcf7 2022-09-13 op file->errors++;
296 b0a6bcf7 2022-09-13 op va_start(ap, fmt);
297 b0a6bcf7 2022-09-13 op if (vasprintf(&msg, fmt, ap) == -1)
298 b0a6bcf7 2022-09-13 op fatal("yyerror vasprintf");
299 b0a6bcf7 2022-09-13 op va_end(ap);
300 b0a6bcf7 2022-09-13 op log_warnx("%s:%d: %s", file->name, yylval.lineno, msg);
301 b0a6bcf7 2022-09-13 op free(msg);
302 b0a6bcf7 2022-09-13 op return (0);
303 b0a6bcf7 2022-09-13 op }
304 b0a6bcf7 2022-09-13 op
305 b0a6bcf7 2022-09-13 op int
306 b0a6bcf7 2022-09-13 op kw_cmp(const void *k, const void *e)
307 b0a6bcf7 2022-09-13 op {
308 b0a6bcf7 2022-09-13 op return (strcmp(k, ((const struct keywords *)e)->k_name));
309 b0a6bcf7 2022-09-13 op }
310 b0a6bcf7 2022-09-13 op
311 b0a6bcf7 2022-09-13 op int
312 b0a6bcf7 2022-09-13 op lookup(char *s)
313 b0a6bcf7 2022-09-13 op {
314 b0a6bcf7 2022-09-13 op /* this has to be sorted always */
315 b0a6bcf7 2022-09-13 op static const struct keywords keywords[] = {
316 b0a6bcf7 2022-09-13 op { "chroot", CHROOT },
317 b0a6bcf7 2022-09-13 op { "hostname", HOSTNAME },
318 b0a6bcf7 2022-09-13 op { "include", INCLUDE },
319 b0a6bcf7 2022-09-13 op { "port", PORT },
320 b0a6bcf7 2022-09-13 op { "prefork", PREFORK },
321 b0a6bcf7 2022-09-13 op { "proxy", PROXY },
322 b0a6bcf7 2022-09-13 op { "server", SERVER },
323 b0a6bcf7 2022-09-13 op { "source", SOURCE },
324 b0a6bcf7 2022-09-13 op { "stylesheet", STYLESHEET},
325 b0a6bcf7 2022-09-13 op };
326 b0a6bcf7 2022-09-13 op const struct keywords *p;
327 b0a6bcf7 2022-09-13 op
328 b0a6bcf7 2022-09-13 op p = bsearch(s, keywords, nitems(keywords), sizeof(keywords[0]),
329 b0a6bcf7 2022-09-13 op kw_cmp);
330 b0a6bcf7 2022-09-13 op
331 b0a6bcf7 2022-09-13 op if (p)
332 b0a6bcf7 2022-09-13 op return (p->k_val);
333 b0a6bcf7 2022-09-13 op else
334 b0a6bcf7 2022-09-13 op return (STRING);
335 b0a6bcf7 2022-09-13 op }
336 b0a6bcf7 2022-09-13 op
337 b0a6bcf7 2022-09-13 op #define START_EXPAND 1
338 b0a6bcf7 2022-09-13 op #define DONE_EXPAND 2
339 b0a6bcf7 2022-09-13 op
340 b0a6bcf7 2022-09-13 op static int expanding;
341 b0a6bcf7 2022-09-13 op
342 b0a6bcf7 2022-09-13 op int
343 b0a6bcf7 2022-09-13 op igetc(void)
344 b0a6bcf7 2022-09-13 op {
345 b0a6bcf7 2022-09-13 op int c;
346 b0a6bcf7 2022-09-13 op
347 b0a6bcf7 2022-09-13 op while (1) {
348 b0a6bcf7 2022-09-13 op if (file->ungetpos > 0)
349 b0a6bcf7 2022-09-13 op c = file->ungetbuf[--file->ungetpos];
350 b0a6bcf7 2022-09-13 op else
351 b0a6bcf7 2022-09-13 op c = getc(file->stream);
352 b0a6bcf7 2022-09-13 op
353 b0a6bcf7 2022-09-13 op if (c == START_EXPAND)
354 b0a6bcf7 2022-09-13 op expanding = 1;
355 b0a6bcf7 2022-09-13 op else if (c == DONE_EXPAND)
356 b0a6bcf7 2022-09-13 op expanding = 0;
357 b0a6bcf7 2022-09-13 op else
358 b0a6bcf7 2022-09-13 op break;
359 b0a6bcf7 2022-09-13 op }
360 b0a6bcf7 2022-09-13 op return (c);
361 b0a6bcf7 2022-09-13 op }
362 b0a6bcf7 2022-09-13 op
363 b0a6bcf7 2022-09-13 op int
364 b0a6bcf7 2022-09-13 op lgetc(int quotec)
365 b0a6bcf7 2022-09-13 op {
366 b0a6bcf7 2022-09-13 op int c, next;
367 b0a6bcf7 2022-09-13 op
368 b0a6bcf7 2022-09-13 op if (quotec) {
369 b0a6bcf7 2022-09-13 op if ((c = igetc()) == EOF) {
370 b0a6bcf7 2022-09-13 op yyerror("reached end of file while parsing "
371 b0a6bcf7 2022-09-13 op "quoted string");
372 b0a6bcf7 2022-09-13 op if (file == topfile || popfile() == EOF)
373 b0a6bcf7 2022-09-13 op return (EOF);
374 b0a6bcf7 2022-09-13 op return (quotec);
375 b0a6bcf7 2022-09-13 op }
376 b0a6bcf7 2022-09-13 op return (c);
377 b0a6bcf7 2022-09-13 op }
378 b0a6bcf7 2022-09-13 op
379 b0a6bcf7 2022-09-13 op while ((c = igetc()) == '\\') {
380 b0a6bcf7 2022-09-13 op next = igetc();
381 b0a6bcf7 2022-09-13 op if (next != '\n') {
382 b0a6bcf7 2022-09-13 op c = next;
383 b0a6bcf7 2022-09-13 op break;
384 b0a6bcf7 2022-09-13 op }
385 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
386 b0a6bcf7 2022-09-13 op file->lineno++;
387 b0a6bcf7 2022-09-13 op }
388 b0a6bcf7 2022-09-13 op if (c == '\t' || c == ' ') {
389 b0a6bcf7 2022-09-13 op /* Compress blanks to a single space. */
390 b0a6bcf7 2022-09-13 op do {
391 b0a6bcf7 2022-09-13 op c = getc(file->stream);
392 b0a6bcf7 2022-09-13 op } while (c == '\t' || c == ' ');
393 b0a6bcf7 2022-09-13 op ungetc(c, file->stream);
394 b0a6bcf7 2022-09-13 op c = ' ';
395 b0a6bcf7 2022-09-13 op }
396 b0a6bcf7 2022-09-13 op
397 b0a6bcf7 2022-09-13 op if (c == EOF) {
398 b0a6bcf7 2022-09-13 op /*
399 b0a6bcf7 2022-09-13 op * Fake EOL when hit EOF for the first time. This gets line
400 b0a6bcf7 2022-09-13 op * count right if last line in included file is syntactically
401 b0a6bcf7 2022-09-13 op * invalid and has no newline.
402 b0a6bcf7 2022-09-13 op */
403 b0a6bcf7 2022-09-13 op if (file->eof_reached == 0) {
404 b0a6bcf7 2022-09-13 op file->eof_reached = 1;
405 b0a6bcf7 2022-09-13 op return ('\n');
406 b0a6bcf7 2022-09-13 op }
407 b0a6bcf7 2022-09-13 op while (c == EOF) {
408 b0a6bcf7 2022-09-13 op if (file == topfile || popfile() == EOF)
409 b0a6bcf7 2022-09-13 op return (EOF);
410 b0a6bcf7 2022-09-13 op c = igetc();
411 b0a6bcf7 2022-09-13 op }
412 b0a6bcf7 2022-09-13 op }
413 b0a6bcf7 2022-09-13 op return (c);
414 b0a6bcf7 2022-09-13 op }
415 b0a6bcf7 2022-09-13 op
416 b0a6bcf7 2022-09-13 op void
417 b0a6bcf7 2022-09-13 op lungetc(int c)
418 b0a6bcf7 2022-09-13 op {
419 b0a6bcf7 2022-09-13 op if (c == EOF)
420 b0a6bcf7 2022-09-13 op return;
421 b0a6bcf7 2022-09-13 op
422 b0a6bcf7 2022-09-13 op if (file->ungetpos >= file->ungetsize) {
423 b0a6bcf7 2022-09-13 op void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
424 b0a6bcf7 2022-09-13 op if (p == NULL)
425 b0a6bcf7 2022-09-13 op err(1, "%s", __func__);
426 b0a6bcf7 2022-09-13 op file->ungetbuf = p;
427 b0a6bcf7 2022-09-13 op file->ungetsize *= 2;
428 b0a6bcf7 2022-09-13 op }
429 b0a6bcf7 2022-09-13 op file->ungetbuf[file->ungetpos++] = c;
430 b0a6bcf7 2022-09-13 op }
431 b0a6bcf7 2022-09-13 op
432 b0a6bcf7 2022-09-13 op int
433 b0a6bcf7 2022-09-13 op findeol(void)
434 b0a6bcf7 2022-09-13 op {
435 b0a6bcf7 2022-09-13 op int c;
436 b0a6bcf7 2022-09-13 op
437 b0a6bcf7 2022-09-13 op /* skip to either EOF or the first real EOL */
438 b0a6bcf7 2022-09-13 op while (1) {
439 b0a6bcf7 2022-09-13 op c = lgetc(0);
440 b0a6bcf7 2022-09-13 op if (c == '\n') {
441 b0a6bcf7 2022-09-13 op file->lineno++;
442 b0a6bcf7 2022-09-13 op break;
443 b0a6bcf7 2022-09-13 op }
444 b0a6bcf7 2022-09-13 op if (c == EOF)
445 b0a6bcf7 2022-09-13 op break;
446 b0a6bcf7 2022-09-13 op }
447 b0a6bcf7 2022-09-13 op return (ERROR);
448 b0a6bcf7 2022-09-13 op }
449 b0a6bcf7 2022-09-13 op
450 b0a6bcf7 2022-09-13 op int
451 b0a6bcf7 2022-09-13 op yylex(void)
452 b0a6bcf7 2022-09-13 op {
453 b0a6bcf7 2022-09-13 op char buf[8096];
454 b0a6bcf7 2022-09-13 op char *p, *val;
455 b0a6bcf7 2022-09-13 op int quotec, next, c;
456 b0a6bcf7 2022-09-13 op int token;
457 b0a6bcf7 2022-09-13 op
458 b0a6bcf7 2022-09-13 op top:
459 b0a6bcf7 2022-09-13 op p = buf;
460 b0a6bcf7 2022-09-13 op while ((c = lgetc(0)) == ' ' || c == '\t')
461 b0a6bcf7 2022-09-13 op ; /* nothing */
462 b0a6bcf7 2022-09-13 op
463 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
464 b0a6bcf7 2022-09-13 op if (c == '#')
465 b0a6bcf7 2022-09-13 op while ((c = lgetc(0)) != '\n' && c != EOF)
466 b0a6bcf7 2022-09-13 op ; /* nothing */
467 b0a6bcf7 2022-09-13 op if (c == '$' && !expanding) {
468 b0a6bcf7 2022-09-13 op while (1) {
469 b0a6bcf7 2022-09-13 op if ((c = lgetc(0)) == EOF)
470 b0a6bcf7 2022-09-13 op return (0);
471 b0a6bcf7 2022-09-13 op
472 b0a6bcf7 2022-09-13 op if (p + 1 >= buf + sizeof(buf) - 1) {
473 b0a6bcf7 2022-09-13 op yyerror("string too long");
474 b0a6bcf7 2022-09-13 op return (findeol());
475 b0a6bcf7 2022-09-13 op }
476 b0a6bcf7 2022-09-13 op if (isalnum(c) || c == '_') {
477 b0a6bcf7 2022-09-13 op *p++ = c;
478 b0a6bcf7 2022-09-13 op continue;
479 b0a6bcf7 2022-09-13 op }
480 b0a6bcf7 2022-09-13 op *p = '\0';
481 b0a6bcf7 2022-09-13 op lungetc(c);
482 b0a6bcf7 2022-09-13 op break;
483 b0a6bcf7 2022-09-13 op }
484 b0a6bcf7 2022-09-13 op val = symget(buf);
485 b0a6bcf7 2022-09-13 op if (val == NULL) {
486 b0a6bcf7 2022-09-13 op yyerror("macro '%s' not defined", buf);
487 b0a6bcf7 2022-09-13 op return (findeol());
488 b0a6bcf7 2022-09-13 op }
489 b0a6bcf7 2022-09-13 op p = val + strlen(val) - 1;
490 b0a6bcf7 2022-09-13 op lungetc(DONE_EXPAND);
491 b0a6bcf7 2022-09-13 op while (p >= val) {
492 b0a6bcf7 2022-09-13 op lungetc((unsigned char)*p);
493 b0a6bcf7 2022-09-13 op p--;
494 b0a6bcf7 2022-09-13 op }
495 b0a6bcf7 2022-09-13 op lungetc(START_EXPAND);
496 b0a6bcf7 2022-09-13 op goto top;
497 b0a6bcf7 2022-09-13 op }
498 b0a6bcf7 2022-09-13 op
499 b0a6bcf7 2022-09-13 op switch (c) {
500 b0a6bcf7 2022-09-13 op case '\'':
501 b0a6bcf7 2022-09-13 op case '"':
502 b0a6bcf7 2022-09-13 op quotec = c;
503 b0a6bcf7 2022-09-13 op while (1) {
504 b0a6bcf7 2022-09-13 op if ((c = lgetc(quotec)) == EOF)
505 b0a6bcf7 2022-09-13 op return (0);
506 b0a6bcf7 2022-09-13 op if (c == '\n') {
507 b0a6bcf7 2022-09-13 op file->lineno++;
508 b0a6bcf7 2022-09-13 op continue;
509 b0a6bcf7 2022-09-13 op } else if (c == '\\') {
510 b0a6bcf7 2022-09-13 op if ((next = lgetc(quotec)) == EOF)
511 b0a6bcf7 2022-09-13 op return (0);
512 b0a6bcf7 2022-09-13 op if (next == quotec || next == ' ' ||
513 b0a6bcf7 2022-09-13 op next == '\t')
514 b0a6bcf7 2022-09-13 op c = next;
515 b0a6bcf7 2022-09-13 op else if (next == '\n') {
516 b0a6bcf7 2022-09-13 op file->lineno++;
517 b0a6bcf7 2022-09-13 op continue;
518 b0a6bcf7 2022-09-13 op } else
519 b0a6bcf7 2022-09-13 op lungetc(next);
520 b0a6bcf7 2022-09-13 op } else if (c == quotec) {
521 b0a6bcf7 2022-09-13 op *p = '\0';
522 b0a6bcf7 2022-09-13 op break;
523 b0a6bcf7 2022-09-13 op } else if (c == '\0') {
524 b0a6bcf7 2022-09-13 op yyerror("syntax error");
525 b0a6bcf7 2022-09-13 op return (findeol());
526 b0a6bcf7 2022-09-13 op }
527 b0a6bcf7 2022-09-13 op if (p + 1 >= buf + sizeof(buf) - 1) {
528 b0a6bcf7 2022-09-13 op yyerror("string too long");
529 b0a6bcf7 2022-09-13 op return (findeol());
530 b0a6bcf7 2022-09-13 op }
531 b0a6bcf7 2022-09-13 op *p++ = c;
532 b0a6bcf7 2022-09-13 op }
533 b0a6bcf7 2022-09-13 op yylval.v.string = strdup(buf);
534 b0a6bcf7 2022-09-13 op if (yylval.v.string == NULL)
535 b0a6bcf7 2022-09-13 op fatal("yylex: strdup");
536 b0a6bcf7 2022-09-13 op return (STRING);
537 b0a6bcf7 2022-09-13 op }
538 b0a6bcf7 2022-09-13 op
539 b0a6bcf7 2022-09-13 op #define allowed_to_end_number(x) \
540 b0a6bcf7 2022-09-13 op (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
541 b0a6bcf7 2022-09-13 op
542 b0a6bcf7 2022-09-13 op if (c == '-' || isdigit(c)) {
543 b0a6bcf7 2022-09-13 op do {
544 b0a6bcf7 2022-09-13 op *p++ = c;
545 b0a6bcf7 2022-09-13 op if ((size_t)(p-buf) >= sizeof(buf)) {
546 b0a6bcf7 2022-09-13 op yyerror("string too long");
547 b0a6bcf7 2022-09-13 op return (findeol());
548 b0a6bcf7 2022-09-13 op }
549 b0a6bcf7 2022-09-13 op } while ((c = lgetc(0)) != EOF && isdigit(c));
550 b0a6bcf7 2022-09-13 op lungetc(c);
551 b0a6bcf7 2022-09-13 op if (p == buf + 1 && buf[0] == '-')
552 b0a6bcf7 2022-09-13 op goto nodigits;
553 b0a6bcf7 2022-09-13 op if (c == EOF || allowed_to_end_number(c)) {
554 b0a6bcf7 2022-09-13 op const char *errstr = NULL;
555 b0a6bcf7 2022-09-13 op
556 b0a6bcf7 2022-09-13 op *p = '\0';
557 b0a6bcf7 2022-09-13 op yylval.v.number = strtonum(buf, LLONG_MIN,
558 b0a6bcf7 2022-09-13 op LLONG_MAX, &errstr);
559 b0a6bcf7 2022-09-13 op if (errstr) {
560 b0a6bcf7 2022-09-13 op yyerror("\"%s\" invalid number: %s",
561 b0a6bcf7 2022-09-13 op buf, errstr);
562 b0a6bcf7 2022-09-13 op return (findeol());
563 b0a6bcf7 2022-09-13 op }
564 b0a6bcf7 2022-09-13 op return (NUMBER);
565 b0a6bcf7 2022-09-13 op } else {
566 b0a6bcf7 2022-09-13 op nodigits:
567 b0a6bcf7 2022-09-13 op while (p > buf + 1)
568 b0a6bcf7 2022-09-13 op lungetc((unsigned char)*--p);
569 b0a6bcf7 2022-09-13 op c = (unsigned char)*--p;
570 b0a6bcf7 2022-09-13 op if (c == '-')
571 b0a6bcf7 2022-09-13 op return (c);
572 b0a6bcf7 2022-09-13 op }
573 b0a6bcf7 2022-09-13 op }
574 b0a6bcf7 2022-09-13 op
575 b0a6bcf7 2022-09-13 op #define allowed_in_string(x) \
576 b0a6bcf7 2022-09-13 op (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
577 b0a6bcf7 2022-09-13 op x != '{' && x != '}' && \
578 b0a6bcf7 2022-09-13 op x != '!' && x != '=' && x != '#' && \
579 b0a6bcf7 2022-09-13 op x != ','))
580 b0a6bcf7 2022-09-13 op
581 b0a6bcf7 2022-09-13 op if (isalnum(c) || c == ':' || c == '_' || c == '/') {
582 b0a6bcf7 2022-09-13 op do {
583 b0a6bcf7 2022-09-13 op *p++ = c;
584 b0a6bcf7 2022-09-13 op if ((size_t)(p-buf) >= sizeof(buf)) {
585 b0a6bcf7 2022-09-13 op yyerror("string too long");
586 b0a6bcf7 2022-09-13 op return (findeol());
587 b0a6bcf7 2022-09-13 op }
588 b0a6bcf7 2022-09-13 op } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
589 b0a6bcf7 2022-09-13 op lungetc(c);
590 b0a6bcf7 2022-09-13 op *p = '\0';
591 b0a6bcf7 2022-09-13 op if ((token = lookup(buf)) == STRING)
592 b0a6bcf7 2022-09-13 op if ((yylval.v.string = strdup(buf)) == NULL)
593 b0a6bcf7 2022-09-13 op fatal("yylex: strdup");
594 b0a6bcf7 2022-09-13 op return (token);
595 b0a6bcf7 2022-09-13 op }
596 b0a6bcf7 2022-09-13 op if (c == '\n') {
597 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
598 b0a6bcf7 2022-09-13 op file->lineno++;
599 b0a6bcf7 2022-09-13 op }
600 b0a6bcf7 2022-09-13 op if (c == EOF)
601 b0a6bcf7 2022-09-13 op return (0);
602 b0a6bcf7 2022-09-13 op return (c);
603 b0a6bcf7 2022-09-13 op }
604 b0a6bcf7 2022-09-13 op
605 b0a6bcf7 2022-09-13 op struct file *
606 b0a6bcf7 2022-09-13 op pushfile(const char *name, int secret)
607 b0a6bcf7 2022-09-13 op {
608 b0a6bcf7 2022-09-13 op struct file *nfile;
609 b0a6bcf7 2022-09-13 op
610 b0a6bcf7 2022-09-13 op if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
611 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
612 b0a6bcf7 2022-09-13 op return (NULL);
613 b0a6bcf7 2022-09-13 op }
614 b0a6bcf7 2022-09-13 op if ((nfile->name = strdup(name)) == NULL) {
615 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
616 b0a6bcf7 2022-09-13 op free(nfile);
617 b0a6bcf7 2022-09-13 op return (NULL);
618 b0a6bcf7 2022-09-13 op }
619 b0a6bcf7 2022-09-13 op if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
620 b0a6bcf7 2022-09-13 op free(nfile->name);
621 b0a6bcf7 2022-09-13 op free(nfile);
622 b0a6bcf7 2022-09-13 op return (NULL);
623 b0a6bcf7 2022-09-13 op }
624 b0a6bcf7 2022-09-13 op nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
625 b0a6bcf7 2022-09-13 op nfile->ungetsize = 16;
626 b0a6bcf7 2022-09-13 op nfile->ungetbuf = malloc(nfile->ungetsize);
627 b0a6bcf7 2022-09-13 op if (nfile->ungetbuf == NULL) {
628 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
629 b0a6bcf7 2022-09-13 op fclose(nfile->stream);
630 b0a6bcf7 2022-09-13 op free(nfile->name);
631 b0a6bcf7 2022-09-13 op free(nfile);
632 b0a6bcf7 2022-09-13 op return (NULL);
633 b0a6bcf7 2022-09-13 op }
634 b0a6bcf7 2022-09-13 op TAILQ_INSERT_TAIL(&files, nfile, entry);
635 b0a6bcf7 2022-09-13 op return (nfile);
636 b0a6bcf7 2022-09-13 op }
637 b0a6bcf7 2022-09-13 op
638 b0a6bcf7 2022-09-13 op int
639 b0a6bcf7 2022-09-13 op popfile(void)
640 b0a6bcf7 2022-09-13 op {
641 b0a6bcf7 2022-09-13 op struct file *prev;
642 b0a6bcf7 2022-09-13 op
643 b0a6bcf7 2022-09-13 op if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
644 b0a6bcf7 2022-09-13 op prev->errors += file->errors;
645 b0a6bcf7 2022-09-13 op
646 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&files, file, entry);
647 b0a6bcf7 2022-09-13 op fclose(file->stream);
648 b0a6bcf7 2022-09-13 op free(file->name);
649 b0a6bcf7 2022-09-13 op free(file->ungetbuf);
650 b0a6bcf7 2022-09-13 op free(file);
651 b0a6bcf7 2022-09-13 op file = prev;
652 b0a6bcf7 2022-09-13 op return (file ? 0 : EOF);
653 b0a6bcf7 2022-09-13 op }
654 b0a6bcf7 2022-09-13 op
655 b0a6bcf7 2022-09-13 op int
656 b0a6bcf7 2022-09-13 op parse_config(const char *filename, struct galileo *env)
657 b0a6bcf7 2022-09-13 op {
658 b0a6bcf7 2022-09-13 op struct sym *sym, *next;
659 b0a6bcf7 2022-09-13 op size_t n;
660 b0a6bcf7 2022-09-13 op
661 b0a6bcf7 2022-09-13 op conf = env;
662 b0a6bcf7 2022-09-13 op
663 b0a6bcf7 2022-09-13 op n = strlcpy(conf->sc_conffile, filename, sizeof(conf->sc_conffile));
664 b0a6bcf7 2022-09-13 op if (n >= sizeof(conf->sc_conffile)) {
665 b0a6bcf7 2022-09-13 op log_warn("path too long: %s", filename);
666 b0a6bcf7 2022-09-13 op return (-1);
667 b0a6bcf7 2022-09-13 op }
668 b0a6bcf7 2022-09-13 op
669 b0a6bcf7 2022-09-13 op if ((file = pushfile(filename, 0)) == NULL) {
670 b0a6bcf7 2022-09-13 op log_warn("failed to open %s", filename);
671 b0a6bcf7 2022-09-13 op return (-1);
672 b0a6bcf7 2022-09-13 op }
673 b0a6bcf7 2022-09-13 op topfile = file;
674 b0a6bcf7 2022-09-13 op setservent(1);
675 b0a6bcf7 2022-09-13 op
676 b0a6bcf7 2022-09-13 op yyparse();
677 b0a6bcf7 2022-09-13 op errors = file->errors;
678 b0a6bcf7 2022-09-13 op popfile();
679 b0a6bcf7 2022-09-13 op
680 b0a6bcf7 2022-09-13 op endservent();
681 b0a6bcf7 2022-09-13 op
682 b0a6bcf7 2022-09-13 op /* Free macros and check which have not been used. */
683 b0a6bcf7 2022-09-13 op TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
684 b0a6bcf7 2022-09-13 op if (!sym->used)
685 b0a6bcf7 2022-09-13 op fprintf(stderr, "warning: macro `%s' not used\n",
686 b0a6bcf7 2022-09-13 op sym->nam);
687 b0a6bcf7 2022-09-13 op if (!sym->persist) {
688 b0a6bcf7 2022-09-13 op free(sym->nam);
689 b0a6bcf7 2022-09-13 op free(sym->val);
690 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&symhead, sym, entry);
691 b0a6bcf7 2022-09-13 op free(sym);
692 b0a6bcf7 2022-09-13 op }
693 b0a6bcf7 2022-09-13 op }
694 b0a6bcf7 2022-09-13 op
695 b0a6bcf7 2022-09-13 op if (errors)
696 b0a6bcf7 2022-09-13 op return (-1);
697 b0a6bcf7 2022-09-13 op
698 b0a6bcf7 2022-09-13 op return (0);
699 b0a6bcf7 2022-09-13 op }
700 b0a6bcf7 2022-09-13 op
701 b0a6bcf7 2022-09-13 op int
702 b0a6bcf7 2022-09-13 op symset(const char *nam, const char *val, int persist)
703 b0a6bcf7 2022-09-13 op {
704 b0a6bcf7 2022-09-13 op struct sym *sym;
705 b0a6bcf7 2022-09-13 op
706 b0a6bcf7 2022-09-13 op TAILQ_FOREACH(sym, &symhead, entry) {
707 b0a6bcf7 2022-09-13 op if (strcmp(nam, sym->nam) == 0)
708 b0a6bcf7 2022-09-13 op break;
709 b0a6bcf7 2022-09-13 op }
710 b0a6bcf7 2022-09-13 op
711 b0a6bcf7 2022-09-13 op if (sym != NULL) {
712 b0a6bcf7 2022-09-13 op if (sym->persist == 1)
713 b0a6bcf7 2022-09-13 op return (0);
714 b0a6bcf7 2022-09-13 op else {
715 b0a6bcf7 2022-09-13 op free(sym->nam);
716 b0a6bcf7 2022-09-13 op free(sym->val);
717 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&symhead, sym, entry);
718 b0a6bcf7 2022-09-13 op free(sym);
719 b0a6bcf7 2022-09-13 op }
720 b0a6bcf7 2022-09-13 op }
721 b0a6bcf7 2022-09-13 op if ((sym = calloc(1, sizeof(*sym))) == NULL)
722 b0a6bcf7 2022-09-13 op return (-1);
723 b0a6bcf7 2022-09-13 op
724 b0a6bcf7 2022-09-13 op sym->nam = strdup(nam);
725 b0a6bcf7 2022-09-13 op if (sym->nam == NULL) {
726 b0a6bcf7 2022-09-13 op free(sym);
727 b0a6bcf7 2022-09-13 op return (-1);
728 b0a6bcf7 2022-09-13 op }
729 b0a6bcf7 2022-09-13 op sym->val = strdup(val);
730 b0a6bcf7 2022-09-13 op if (sym->val == NULL) {
731 b0a6bcf7 2022-09-13 op free(sym->nam);
732 b0a6bcf7 2022-09-13 op free(sym);
733 b0a6bcf7 2022-09-13 op return (-1);
734 b0a6bcf7 2022-09-13 op }
735 b0a6bcf7 2022-09-13 op sym->used = 0;
736 b0a6bcf7 2022-09-13 op sym->persist = persist;
737 b0a6bcf7 2022-09-13 op TAILQ_INSERT_TAIL(&symhead, sym, entry);
738 b0a6bcf7 2022-09-13 op return (0);
739 b0a6bcf7 2022-09-13 op }
740 b0a6bcf7 2022-09-13 op
741 b0a6bcf7 2022-09-13 op int
742 b0a6bcf7 2022-09-13 op cmdline_symset(char *s)
743 b0a6bcf7 2022-09-13 op {
744 b0a6bcf7 2022-09-13 op char *sym, *val;
745 b0a6bcf7 2022-09-13 op int ret;
746 b0a6bcf7 2022-09-13 op
747 b0a6bcf7 2022-09-13 op if ((val = strrchr(s, '=')) == NULL)
748 b0a6bcf7 2022-09-13 op return (-1);
749 b0a6bcf7 2022-09-13 op sym = strndup(s, val - s);
750 b0a6bcf7 2022-09-13 op if (sym == NULL)
751 b0a6bcf7 2022-09-13 op fatal("%s: strndup", __func__);
752 b0a6bcf7 2022-09-13 op ret = symset(sym, val + 1, 1);
753 b0a6bcf7 2022-09-13 op free(sym);
754 b0a6bcf7 2022-09-13 op
755 b0a6bcf7 2022-09-13 op return (ret);
756 b0a6bcf7 2022-09-13 op }
757 b0a6bcf7 2022-09-13 op
758 b0a6bcf7 2022-09-13 op char *
759 b0a6bcf7 2022-09-13 op symget(const char *nam)
760 b0a6bcf7 2022-09-13 op {
761 b0a6bcf7 2022-09-13 op struct sym *sym;
762 b0a6bcf7 2022-09-13 op
763 b0a6bcf7 2022-09-13 op TAILQ_FOREACH(sym, &symhead, entry) {
764 b0a6bcf7 2022-09-13 op if (strcmp(nam, sym->nam) == 0) {
765 b0a6bcf7 2022-09-13 op sym->used = 1;
766 b0a6bcf7 2022-09-13 op return (sym->val);
767 b0a6bcf7 2022-09-13 op }
768 b0a6bcf7 2022-09-13 op }
769 b0a6bcf7 2022-09-13 op return (NULL);
770 b0a6bcf7 2022-09-13 op }
771 b0a6bcf7 2022-09-13 op
772 b0a6bcf7 2022-09-13 op int
773 b0a6bcf7 2022-09-13 op getservice(const char *n)
774 b0a6bcf7 2022-09-13 op {
775 b0a6bcf7 2022-09-13 op struct servent *s;
776 b0a6bcf7 2022-09-13 op const char *errstr;
777 b0a6bcf7 2022-09-13 op long long llval;
778 b0a6bcf7 2022-09-13 op
779 b0a6bcf7 2022-09-13 op llval = strtonum(n, 0, UINT16_MAX, &errstr);
780 b0a6bcf7 2022-09-13 op if (errstr) {
781 b0a6bcf7 2022-09-13 op s = getservbyname(n, "tcp");
782 b0a6bcf7 2022-09-13 op if (s == NULL)
783 b0a6bcf7 2022-09-13 op s = getservbyname(n, "udp");
784 b0a6bcf7 2022-09-13 op if (s == NULL)
785 b0a6bcf7 2022-09-13 op return (-1);
786 b0a6bcf7 2022-09-13 op return (ntohs(s->s_port));
787 b0a6bcf7 2022-09-13 op }
788 b0a6bcf7 2022-09-13 op
789 b0a6bcf7 2022-09-13 op return ((unsigned short)llval);
790 b0a6bcf7 2022-09-13 op }