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.
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.
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.
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>
30 b0a6bcf7 2022-09-13 op #include <err.h>
31 b0a6bcf7 2022-09-13 op #include <event.h>
32 65015347 2022-09-29 op #include <inttypes.h>
33 b0a6bcf7 2022-09-13 op #include <netdb.h>
34 b0a6bcf7 2022-09-13 op #include <stdio.h>
35 b0a6bcf7 2022-09-13 op #include <stdlib.h>
36 b0a6bcf7 2022-09-13 op #include <limits.h>
37 b0a6bcf7 2022-09-13 op #include <stdarg.h>
38 b0a6bcf7 2022-09-13 op #include <stdint.h>
39 b0a6bcf7 2022-09-13 op #include <string.h>
40 b0a6bcf7 2022-09-13 op #include <unistd.h>
41 b0a6bcf7 2022-09-13 op #include <ctype.h>
42 b0a6bcf7 2022-09-13 op #include <errno.h>
43 b0a6bcf7 2022-09-13 op #include <fcntl.h>
44 b0a6bcf7 2022-09-13 op #include <pwd.h>
45 b0a6bcf7 2022-09-13 op #include <imsg.h>
47 b0a6bcf7 2022-09-13 op #include "log.h"
48 b0a6bcf7 2022-09-13 op #include "proc.h"
50 b0a6bcf7 2022-09-13 op #include "galileo.h"
52 b0a6bcf7 2022-09-13 op TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
53 b0a6bcf7 2022-09-13 op static struct file {
54 b0a6bcf7 2022-09-13 op TAILQ_ENTRY(file) entry;
57 b0a6bcf7 2022-09-13 op size_t ungetpos;
58 b0a6bcf7 2022-09-13 op size_t ungetsize;
59 b0a6bcf7 2022-09-13 op u_char *ungetbuf;
60 b0a6bcf7 2022-09-13 op int eof_reached;
63 b0a6bcf7 2022-09-13 op } *file, *topfile;
64 b0a6bcf7 2022-09-13 op struct file *pushfile(const char *, int);
65 b0a6bcf7 2022-09-13 op int popfile(void);
66 b0a6bcf7 2022-09-13 op int yyparse(void);
67 b0a6bcf7 2022-09-13 op int yylex(void);
68 b0a6bcf7 2022-09-13 op int yyerror(const char *, ...)
69 b0a6bcf7 2022-09-13 op __attribute__((__format__ (printf, 1, 2)))
70 b0a6bcf7 2022-09-13 op __attribute__((__nonnull__ (1)));
71 b0a6bcf7 2022-09-13 op int kw_cmp(const void *, const void *);
72 b0a6bcf7 2022-09-13 op int lookup(char *);
73 b0a6bcf7 2022-09-13 op int igetc(void);
74 b0a6bcf7 2022-09-13 op int lgetc(int);
75 b0a6bcf7 2022-09-13 op void lungetc(int);
76 b0a6bcf7 2022-09-13 op int findeol(void);
78 b0a6bcf7 2022-09-13 op TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
80 b0a6bcf7 2022-09-13 op TAILQ_ENTRY(sym) entry;
86 b0a6bcf7 2022-09-13 op int symset(const char *, const char *, int);
87 b0a6bcf7 2022-09-13 op char *symget(const char *);
89 b0a6bcf7 2022-09-13 op int getservice(const char *);
91 b0a6bcf7 2022-09-13 op static struct galileo *conf = NULL;
92 afb86b2c 2022-09-23 op static struct proxy *pr = NULL;
93 b0a6bcf7 2022-09-13 op static int errors;
95 b0a6bcf7 2022-09-13 op typedef struct {
97 b0a6bcf7 2022-09-13 op int64_t number;
105 b0a6bcf7 2022-09-13 op %token INCLUDE ERROR
106 da7b17a3 2023-03-03 op %token BAR CHROOT FOOTER HOSTNAME IMAGE NAVIGATION NO PORT
107 da7b17a3 2023-03-03 op %token PREFORK PREVIEW PROXY SOURCE STYLESHEET TLS
108 35adaaa9 2022-09-23 op %token <v.number> NUMBER
109 35adaaa9 2022-09-23 op %token <v.string> STRING
110 b0a6bcf7 2022-09-13 op %type <v.number> port
111 b0a6bcf7 2022-09-13 op %type <v.string> string
115 b0a6bcf7 2022-09-13 op grammar : /* empty */
116 b0a6bcf7 2022-09-13 op | grammar include '\n'
117 b0a6bcf7 2022-09-13 op | grammar '\n'
118 b0a6bcf7 2022-09-13 op | grammar varset '\n'
119 b0a6bcf7 2022-09-13 op | grammar main '\n'
120 afb86b2c 2022-09-23 op | grammar proxy '\n'
121 b0a6bcf7 2022-09-13 op | grammar error '\n' { file->errors++; }
124 b0a6bcf7 2022-09-13 op include : INCLUDE string {
125 b0a6bcf7 2022-09-13 op struct file *nfile;
127 b0a6bcf7 2022-09-13 op if ((nfile = pushfile($2, 0)) == NULL) {
128 b0a6bcf7 2022-09-13 op yyerror("failed to include file %s", $2);
134 b0a6bcf7 2022-09-13 op file = nfile;
135 b0a6bcf7 2022-09-13 op lungetc('\n');
139 b0a6bcf7 2022-09-13 op varset : STRING '=' STRING {
140 b0a6bcf7 2022-09-13 op char *s = $1;
141 b0a6bcf7 2022-09-13 op while (*s++) {
142 b0a6bcf7 2022-09-13 op if (isspace((unsigned char)*s)) {
143 b0a6bcf7 2022-09-13 op yyerror("macro name cannot contain "
144 b0a6bcf7 2022-09-13 op "whitespace");
150 b0a6bcf7 2022-09-13 op if (symset($1, $3, 0) == -1)
151 b0a6bcf7 2022-09-13 op fatalx("cannot store variable");
157 b0a6bcf7 2022-09-13 op main : PREFORK NUMBER {
158 b0a6bcf7 2022-09-13 op if ($2 <= 0 || $2 > PROC_MAX_INSTANCES) {
159 b0a6bcf7 2022-09-13 op yyerror("invalid number of preforked "
160 65015347 2022-09-29 op "proxies: %"PRId64, $2);
163 b0a6bcf7 2022-09-13 op conf->sc_prefork = $2;
165 b0a6bcf7 2022-09-13 op | CHROOT STRING {
168 b0a6bcf7 2022-09-13 op n = strlcpy(conf->sc_chroot, $2,
169 b0a6bcf7 2022-09-13 op sizeof(conf->sc_chroot));
170 b0a6bcf7 2022-09-13 op if (n >= sizeof(conf->sc_chroot))
171 b0a6bcf7 2022-09-13 op yyerror("chroot path too long!");
176 afb86b2c 2022-09-23 op proxy : PROXY STRING {
177 afb86b2c 2022-09-23 op struct proxy *p;
180 afb86b2c 2022-09-23 op if ((p = calloc(1, sizeof(*p))) == NULL)
181 b0a6bcf7 2022-09-13 op fatal("calloc");
183 afb86b2c 2022-09-23 op n = strlcpy(p->pr_conf.host, $2,
184 afb86b2c 2022-09-23 op sizeof(p->pr_conf.host));
185 afb86b2c 2022-09-23 op if (n >= sizeof(p->pr_conf.host)) {
186 b0a6bcf7 2022-09-13 op yyerror("server name too long");
194 afb86b2c 2022-09-23 op } '{' optnl proxyopts_l '}' {
195 b0a6bcf7 2022-09-13 op /* check if duplicate */
196 979cc5fd 2022-09-23 op if (proxy_match(conf, pr->pr_conf.host) != NULL)
197 979cc5fd 2022-09-23 op yyerror("duplicate proxy `%s'",
198 979cc5fd 2022-09-23 op pr->pr_conf.host);
200 979cc5fd 2022-09-23 op TAILQ_INSERT_TAIL(&conf->sc_proxies, pr, pr_entry);
202 c464d38a 2022-09-23 op if (*pr->pr_conf.proxy_addr == '\0')
203 c464d38a 2022-09-23 op yyerror("missing source in proxy block `%s'",
204 c464d38a 2022-09-23 op pr->pr_conf.host);
210 afb86b2c 2022-09-23 op proxyopts_l : proxyopts_l proxyoptsl nl
211 afb86b2c 2022-09-23 op | proxyoptsl optnl
214 26cd3e9d 2022-09-23 op proxyoptsl : SOURCE STRING proxyport {
217 afb86b2c 2022-09-23 op n = strlcpy(pr->pr_conf.proxy_addr, $2,
218 afb86b2c 2022-09-23 op sizeof(pr->pr_conf.proxy_addr));
219 afb86b2c 2022-09-23 op if (n >= sizeof(pr->pr_conf.proxy_addr))
220 afb86b2c 2022-09-23 op yyerror("proxy source too long!");
222 917cf063 2022-09-23 op if (*pr->pr_conf.proxy_name == '\0') {
223 917cf063 2022-09-23 op n = strlcpy(pr->pr_conf.proxy_name, $2,
224 917cf063 2022-09-23 op sizeof(pr->pr_conf.proxy_name));
225 917cf063 2022-09-23 op if (n >= sizeof(pr->pr_conf.proxy_name))
226 917cf063 2022-09-23 op yyerror("proxy hostname too long!");
231 afb86b2c 2022-09-23 op | HOSTNAME STRING {
234 afb86b2c 2022-09-23 op n = strlcpy(pr->pr_conf.proxy_name, $2,
235 afb86b2c 2022-09-23 op sizeof(pr->pr_conf.proxy_name));
236 afb86b2c 2022-09-23 op if (n >= sizeof(pr->pr_conf.proxy_name))
237 afb86b2c 2022-09-23 op yyerror("proxy hostname too long!");
240 afb86b2c 2022-09-23 op | STYLESHEET string {
243 afb86b2c 2022-09-23 op n = strlcpy(pr->pr_conf.stylesheet, $2,
244 afb86b2c 2022-09-23 op sizeof(pr->pr_conf.stylesheet));
245 afb86b2c 2022-09-23 op if (n >= sizeof(pr->pr_conf.stylesheet))
246 afb86b2c 2022-09-23 op yyerror("stylesheet path too long!");
249 da7b17a3 2023-03-03 op | NO FOOTER {
250 da7b17a3 2023-03-03 op pr->pr_conf.flags |= PROXY_NO_FOOTER;
252 da7b17a3 2023-03-03 op | NO IMAGE PREVIEW {
253 da7b17a3 2023-03-03 op pr->pr_conf.flags |= PROXY_NO_IMGPRV;
255 da7b17a3 2023-03-03 op | NO NAVIGATION BAR {
256 da7b17a3 2023-03-03 op pr->pr_conf.flags |= PROXY_NO_NAVBAR;
259 da7b17a3 2023-03-03 op pr->pr_conf.flags |= PROXY_NO_TLS;
263 26cd3e9d 2022-09-23 op proxyport : /* empty */ {
264 26cd3e9d 2022-09-23 op strlcpy(pr->pr_conf.proxy_port, "1965",
265 26cd3e9d 2022-09-23 op sizeof(pr->pr_conf.proxy_port));
267 26cd3e9d 2022-09-23 op | PORT port {
271 26cd3e9d 2022-09-23 op len = sizeof(pr->pr_conf.proxy_port);
272 65015347 2022-09-29 op n = snprintf(pr->pr_conf.proxy_port, len,
273 65015347 2022-09-29 op "%"PRId64, $2);
274 26cd3e9d 2022-09-23 op if (n < 0 || (size_t)n >= len)
275 26cd3e9d 2022-09-23 op fatal("port number too long?");
278 b0a6bcf7 2022-09-13 op port : NUMBER {
279 b0a6bcf7 2022-09-13 op if ($1 <= 0 || $1 > (int)USHRT_MAX) {
280 65015347 2022-09-29 op yyerror("invalid port: %"PRId64, $1);
288 b0a6bcf7 2022-09-13 op if ((val = getservice($1)) == -1) {
289 b0a6bcf7 2022-09-13 op yyerror("invalid port: %s", $1);
298 b0a6bcf7 2022-09-13 op string : STRING string {
299 b0a6bcf7 2022-09-13 op if (asprintf(&$$, "%s%s", $1, $2) == -1)
300 b0a6bcf7 2022-09-13 op fatal("asprintf string");
307 b0a6bcf7 2022-09-13 op optnl : '\n' optnl
311 b0a6bcf7 2022-09-13 op nl : '\n' optnl
316 b0a6bcf7 2022-09-13 op struct keywords {
317 b0a6bcf7 2022-09-13 op const char *k_name;
322 b0a6bcf7 2022-09-13 op yyerror(const char *fmt, ...)
327 b0a6bcf7 2022-09-13 op file->errors++;
328 b0a6bcf7 2022-09-13 op va_start(ap, fmt);
329 b0a6bcf7 2022-09-13 op if (vasprintf(&msg, fmt, ap) == -1)
330 b0a6bcf7 2022-09-13 op fatal("yyerror vasprintf");
332 b0a6bcf7 2022-09-13 op log_warnx("%s:%d: %s", file->name, yylval.lineno, msg);
338 b0a6bcf7 2022-09-13 op kw_cmp(const void *k, const void *e)
340 b0a6bcf7 2022-09-13 op return (strcmp(k, ((const struct keywords *)e)->k_name));
344 b0a6bcf7 2022-09-13 op lookup(char *s)
346 b0a6bcf7 2022-09-13 op /* this has to be sorted always */
347 b0a6bcf7 2022-09-13 op static const struct keywords keywords[] = {
348 da7b17a3 2023-03-03 op { "bar", BAR },
349 b0a6bcf7 2022-09-13 op { "chroot", CHROOT },
350 da7b17a3 2023-03-03 op { "footer", FOOTER },
351 b0a6bcf7 2022-09-13 op { "hostname", HOSTNAME },
352 da7b17a3 2023-03-03 op { "image", IMAGE },
353 b0a6bcf7 2022-09-13 op { "include", INCLUDE },
354 da7b17a3 2023-03-03 op { "navigation", NAVIGATION },
355 c743c9a1 2022-09-23 op { "no", NO },
356 b0a6bcf7 2022-09-13 op { "port", PORT },
357 b0a6bcf7 2022-09-13 op { "prefork", PREFORK },
358 da7b17a3 2023-03-03 op { "preview", PREVIEW },
359 b0a6bcf7 2022-09-13 op { "proxy", PROXY },
360 b0a6bcf7 2022-09-13 op { "source", SOURCE },
361 b0a6bcf7 2022-09-13 op { "stylesheet", STYLESHEET},
362 c743c9a1 2022-09-23 op { "tls", TLS },
364 b0a6bcf7 2022-09-13 op const struct keywords *p;
366 b0a6bcf7 2022-09-13 op p = bsearch(s, keywords, nitems(keywords), sizeof(keywords[0]),
370 b0a6bcf7 2022-09-13 op return (p->k_val);
372 b0a6bcf7 2022-09-13 op return (STRING);
375 b0a6bcf7 2022-09-13 op #define START_EXPAND 1
376 b0a6bcf7 2022-09-13 op #define DONE_EXPAND 2
378 b0a6bcf7 2022-09-13 op static int expanding;
386 b0a6bcf7 2022-09-13 op if (file->ungetpos > 0)
387 b0a6bcf7 2022-09-13 op c = file->ungetbuf[--file->ungetpos];
389 b0a6bcf7 2022-09-13 op c = getc(file->stream);
391 b0a6bcf7 2022-09-13 op if (c == START_EXPAND)
392 b0a6bcf7 2022-09-13 op expanding = 1;
393 b0a6bcf7 2022-09-13 op else if (c == DONE_EXPAND)
394 b0a6bcf7 2022-09-13 op expanding = 0;
402 b0a6bcf7 2022-09-13 op lgetc(int quotec)
406 b0a6bcf7 2022-09-13 op if (quotec) {
407 b0a6bcf7 2022-09-13 op if ((c = igetc()) == EOF) {
408 b0a6bcf7 2022-09-13 op yyerror("reached end of file while parsing "
409 b0a6bcf7 2022-09-13 op "quoted string");
410 b0a6bcf7 2022-09-13 op if (file == topfile || popfile() == EOF)
411 b0a6bcf7 2022-09-13 op return (EOF);
412 b0a6bcf7 2022-09-13 op return (quotec);
417 b0a6bcf7 2022-09-13 op while ((c = igetc()) == '\\') {
418 b0a6bcf7 2022-09-13 op next = igetc();
419 b0a6bcf7 2022-09-13 op if (next != '\n') {
423 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
424 b0a6bcf7 2022-09-13 op file->lineno++;
426 b0a6bcf7 2022-09-13 op if (c == '\t' || c == ' ') {
427 b0a6bcf7 2022-09-13 op /* Compress blanks to a single space. */
429 b0a6bcf7 2022-09-13 op c = getc(file->stream);
430 b0a6bcf7 2022-09-13 op } while (c == '\t' || c == ' ');
431 b0a6bcf7 2022-09-13 op ungetc(c, file->stream);
435 b0a6bcf7 2022-09-13 op if (c == EOF) {
437 b0a6bcf7 2022-09-13 op * Fake EOL when hit EOF for the first time. This gets line
438 b0a6bcf7 2022-09-13 op * count right if last line in included file is syntactically
439 b0a6bcf7 2022-09-13 op * invalid and has no newline.
441 b0a6bcf7 2022-09-13 op if (file->eof_reached == 0) {
442 b0a6bcf7 2022-09-13 op file->eof_reached = 1;
443 b0a6bcf7 2022-09-13 op return ('\n');
445 b0a6bcf7 2022-09-13 op while (c == EOF) {
446 b0a6bcf7 2022-09-13 op if (file == topfile || popfile() == EOF)
447 b0a6bcf7 2022-09-13 op return (EOF);
455 b0a6bcf7 2022-09-13 op lungetc(int c)
457 b0a6bcf7 2022-09-13 op if (c == EOF)
460 b0a6bcf7 2022-09-13 op if (file->ungetpos >= file->ungetsize) {
461 b0a6bcf7 2022-09-13 op void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
462 b0a6bcf7 2022-09-13 op if (p == NULL)
463 b0a6bcf7 2022-09-13 op err(1, "%s", __func__);
464 b0a6bcf7 2022-09-13 op file->ungetbuf = p;
465 b0a6bcf7 2022-09-13 op file->ungetsize *= 2;
467 b0a6bcf7 2022-09-13 op file->ungetbuf[file->ungetpos++] = c;
471 b0a6bcf7 2022-09-13 op findeol(void)
475 b0a6bcf7 2022-09-13 op /* skip to either EOF or the first real EOL */
477 b0a6bcf7 2022-09-13 op c = lgetc(0);
478 b0a6bcf7 2022-09-13 op if (c == '\n') {
479 b0a6bcf7 2022-09-13 op file->lineno++;
482 b0a6bcf7 2022-09-13 op if (c == EOF)
485 b0a6bcf7 2022-09-13 op return (ERROR);
491 b0a6bcf7 2022-09-13 op char buf[8096];
492 b0a6bcf7 2022-09-13 op char *p, *val;
493 b0a6bcf7 2022-09-13 op int quotec, next, c;
498 b0a6bcf7 2022-09-13 op while ((c = lgetc(0)) == ' ' || c == '\t')
499 b0a6bcf7 2022-09-13 op ; /* nothing */
501 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
502 b0a6bcf7 2022-09-13 op if (c == '#')
503 b0a6bcf7 2022-09-13 op while ((c = lgetc(0)) != '\n' && c != EOF)
504 b0a6bcf7 2022-09-13 op ; /* nothing */
505 b0a6bcf7 2022-09-13 op if (c == '$' && !expanding) {
507 b0a6bcf7 2022-09-13 op if ((c = lgetc(0)) == EOF)
510 b0a6bcf7 2022-09-13 op if (p + 1 >= buf + sizeof(buf) - 1) {
511 b0a6bcf7 2022-09-13 op yyerror("string too long");
512 b0a6bcf7 2022-09-13 op return (findeol());
514 b0a6bcf7 2022-09-13 op if (isalnum(c) || c == '_') {
522 b0a6bcf7 2022-09-13 op val = symget(buf);
523 b0a6bcf7 2022-09-13 op if (val == NULL) {
524 b0a6bcf7 2022-09-13 op yyerror("macro '%s' not defined", buf);
525 b0a6bcf7 2022-09-13 op return (findeol());
527 b0a6bcf7 2022-09-13 op p = val + strlen(val) - 1;
528 b0a6bcf7 2022-09-13 op lungetc(DONE_EXPAND);
529 b0a6bcf7 2022-09-13 op while (p >= val) {
530 b0a6bcf7 2022-09-13 op lungetc((unsigned char)*p);
533 b0a6bcf7 2022-09-13 op lungetc(START_EXPAND);
542 b0a6bcf7 2022-09-13 op if ((c = lgetc(quotec)) == EOF)
544 b0a6bcf7 2022-09-13 op if (c == '\n') {
545 b0a6bcf7 2022-09-13 op file->lineno++;
547 b0a6bcf7 2022-09-13 op } else if (c == '\\') {
548 b0a6bcf7 2022-09-13 op if ((next = lgetc(quotec)) == EOF)
550 b0a6bcf7 2022-09-13 op if (next == quotec || next == ' ' ||
551 b0a6bcf7 2022-09-13 op next == '\t')
553 b0a6bcf7 2022-09-13 op else if (next == '\n') {
554 b0a6bcf7 2022-09-13 op file->lineno++;
557 b0a6bcf7 2022-09-13 op lungetc(next);
558 b0a6bcf7 2022-09-13 op } else if (c == quotec) {
561 b0a6bcf7 2022-09-13 op } else if (c == '\0') {
562 b0a6bcf7 2022-09-13 op yyerror("syntax error");
563 b0a6bcf7 2022-09-13 op return (findeol());
565 b0a6bcf7 2022-09-13 op if (p + 1 >= buf + sizeof(buf) - 1) {
566 b0a6bcf7 2022-09-13 op yyerror("string too long");
567 b0a6bcf7 2022-09-13 op return (findeol());
571 b0a6bcf7 2022-09-13 op yylval.v.string = strdup(buf);
572 b0a6bcf7 2022-09-13 op if (yylval.v.string == NULL)
573 b0a6bcf7 2022-09-13 op fatal("yylex: strdup");
574 b0a6bcf7 2022-09-13 op return (STRING);
577 b0a6bcf7 2022-09-13 op #define allowed_to_end_number(x) \
578 b0a6bcf7 2022-09-13 op (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
580 b0a6bcf7 2022-09-13 op if (c == '-' || isdigit(c)) {
583 b0a6bcf7 2022-09-13 op if ((size_t)(p-buf) >= sizeof(buf)) {
584 b0a6bcf7 2022-09-13 op yyerror("string too long");
585 b0a6bcf7 2022-09-13 op return (findeol());
587 b0a6bcf7 2022-09-13 op } while ((c = lgetc(0)) != EOF && isdigit(c));
589 b0a6bcf7 2022-09-13 op if (p == buf + 1 && buf[0] == '-')
590 b0a6bcf7 2022-09-13 op goto nodigits;
591 b0a6bcf7 2022-09-13 op if (c == EOF || allowed_to_end_number(c)) {
592 b0a6bcf7 2022-09-13 op const char *errstr = NULL;
595 b0a6bcf7 2022-09-13 op yylval.v.number = strtonum(buf, LLONG_MIN,
596 b0a6bcf7 2022-09-13 op LLONG_MAX, &errstr);
597 b0a6bcf7 2022-09-13 op if (errstr) {
598 b0a6bcf7 2022-09-13 op yyerror("\"%s\" invalid number: %s",
599 b0a6bcf7 2022-09-13 op buf, errstr);
600 b0a6bcf7 2022-09-13 op return (findeol());
602 b0a6bcf7 2022-09-13 op return (NUMBER);
605 b0a6bcf7 2022-09-13 op while (p > buf + 1)
606 b0a6bcf7 2022-09-13 op lungetc((unsigned char)*--p);
607 b0a6bcf7 2022-09-13 op c = (unsigned char)*--p;
608 b0a6bcf7 2022-09-13 op if (c == '-')
613 b0a6bcf7 2022-09-13 op #define allowed_in_string(x) \
614 b0a6bcf7 2022-09-13 op (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
615 b0a6bcf7 2022-09-13 op x != '{' && x != '}' && \
616 b0a6bcf7 2022-09-13 op x != '!' && x != '=' && x != '#' && \
619 b0a6bcf7 2022-09-13 op if (isalnum(c) || c == ':' || c == '_' || c == '/') {
622 b0a6bcf7 2022-09-13 op if ((size_t)(p-buf) >= sizeof(buf)) {
623 b0a6bcf7 2022-09-13 op yyerror("string too long");
624 b0a6bcf7 2022-09-13 op return (findeol());
626 b0a6bcf7 2022-09-13 op } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
629 b0a6bcf7 2022-09-13 op if ((token = lookup(buf)) == STRING)
630 b0a6bcf7 2022-09-13 op if ((yylval.v.string = strdup(buf)) == NULL)
631 b0a6bcf7 2022-09-13 op fatal("yylex: strdup");
632 b0a6bcf7 2022-09-13 op return (token);
634 b0a6bcf7 2022-09-13 op if (c == '\n') {
635 b0a6bcf7 2022-09-13 op yylval.lineno = file->lineno;
636 b0a6bcf7 2022-09-13 op file->lineno++;
638 b0a6bcf7 2022-09-13 op if (c == EOF)
643 b0a6bcf7 2022-09-13 op struct file *
644 b0a6bcf7 2022-09-13 op pushfile(const char *name, int secret)
646 b0a6bcf7 2022-09-13 op struct file *nfile;
648 b0a6bcf7 2022-09-13 op if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
649 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
650 b0a6bcf7 2022-09-13 op return (NULL);
652 b0a6bcf7 2022-09-13 op if ((nfile->name = strdup(name)) == NULL) {
653 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
655 b0a6bcf7 2022-09-13 op return (NULL);
657 b0a6bcf7 2022-09-13 op if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
658 b0a6bcf7 2022-09-13 op free(nfile->name);
660 b0a6bcf7 2022-09-13 op return (NULL);
662 b0a6bcf7 2022-09-13 op nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
663 b0a6bcf7 2022-09-13 op nfile->ungetsize = 16;
664 b0a6bcf7 2022-09-13 op nfile->ungetbuf = malloc(nfile->ungetsize);
665 b0a6bcf7 2022-09-13 op if (nfile->ungetbuf == NULL) {
666 b0a6bcf7 2022-09-13 op log_warn("%s", __func__);
667 b0a6bcf7 2022-09-13 op fclose(nfile->stream);
668 b0a6bcf7 2022-09-13 op free(nfile->name);
670 b0a6bcf7 2022-09-13 op return (NULL);
672 b0a6bcf7 2022-09-13 op TAILQ_INSERT_TAIL(&files, nfile, entry);
673 b0a6bcf7 2022-09-13 op return (nfile);
677 b0a6bcf7 2022-09-13 op popfile(void)
679 b0a6bcf7 2022-09-13 op struct file *prev;
681 b0a6bcf7 2022-09-13 op if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
682 b0a6bcf7 2022-09-13 op prev->errors += file->errors;
684 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&files, file, entry);
685 b0a6bcf7 2022-09-13 op fclose(file->stream);
686 b0a6bcf7 2022-09-13 op free(file->name);
687 b0a6bcf7 2022-09-13 op free(file->ungetbuf);
690 b0a6bcf7 2022-09-13 op return (file ? 0 : EOF);
694 b0a6bcf7 2022-09-13 op parse_config(const char *filename, struct galileo *env)
696 b0a6bcf7 2022-09-13 op struct sym *sym, *next;
701 b0a6bcf7 2022-09-13 op n = strlcpy(conf->sc_conffile, filename, sizeof(conf->sc_conffile));
702 b0a6bcf7 2022-09-13 op if (n >= sizeof(conf->sc_conffile)) {
703 b0a6bcf7 2022-09-13 op log_warn("path too long: %s", filename);
707 b0a6bcf7 2022-09-13 op if ((file = pushfile(filename, 0)) == NULL) {
708 b0a6bcf7 2022-09-13 op log_warn("failed to open %s", filename);
711 b0a6bcf7 2022-09-13 op topfile = file;
712 b0a6bcf7 2022-09-13 op setservent(1);
715 07866593 2022-09-23 op if (TAILQ_EMPTY(&conf->sc_proxies))
716 07866593 2022-09-23 op yyerror("no proxies defined");
717 b0a6bcf7 2022-09-13 op errors = file->errors;
720 b0a6bcf7 2022-09-13 op endservent();
722 b0a6bcf7 2022-09-13 op /* Free macros and check which have not been used. */
723 b0a6bcf7 2022-09-13 op TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
724 b0a6bcf7 2022-09-13 op if (!sym->used)
725 b0a6bcf7 2022-09-13 op fprintf(stderr, "warning: macro `%s' not used\n",
727 b0a6bcf7 2022-09-13 op if (!sym->persist) {
728 b0a6bcf7 2022-09-13 op free(sym->nam);
729 b0a6bcf7 2022-09-13 op free(sym->val);
730 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&symhead, sym, entry);
742 b0a6bcf7 2022-09-13 op symset(const char *nam, const char *val, int persist)
744 b0a6bcf7 2022-09-13 op struct sym *sym;
746 b0a6bcf7 2022-09-13 op TAILQ_FOREACH(sym, &symhead, entry) {
747 b0a6bcf7 2022-09-13 op if (strcmp(nam, sym->nam) == 0)
751 b0a6bcf7 2022-09-13 op if (sym != NULL) {
752 b0a6bcf7 2022-09-13 op if (sym->persist == 1)
755 b0a6bcf7 2022-09-13 op free(sym->nam);
756 b0a6bcf7 2022-09-13 op free(sym->val);
757 b0a6bcf7 2022-09-13 op TAILQ_REMOVE(&symhead, sym, entry);
761 b0a6bcf7 2022-09-13 op if ((sym = calloc(1, sizeof(*sym))) == NULL)
764 b0a6bcf7 2022-09-13 op sym->nam = strdup(nam);
765 b0a6bcf7 2022-09-13 op if (sym->nam == NULL) {
769 b0a6bcf7 2022-09-13 op sym->val = strdup(val);
770 b0a6bcf7 2022-09-13 op if (sym->val == NULL) {
771 b0a6bcf7 2022-09-13 op free(sym->nam);
775 b0a6bcf7 2022-09-13 op sym->used = 0;
776 b0a6bcf7 2022-09-13 op sym->persist = persist;
777 b0a6bcf7 2022-09-13 op TAILQ_INSERT_TAIL(&symhead, sym, entry);
782 b0a6bcf7 2022-09-13 op cmdline_symset(char *s)
784 b0a6bcf7 2022-09-13 op char *sym, *val;
787 b0a6bcf7 2022-09-13 op if ((val = strrchr(s, '=')) == NULL)
789 b0a6bcf7 2022-09-13 op sym = strndup(s, val - s);
790 b0a6bcf7 2022-09-13 op if (sym == NULL)
791 b0a6bcf7 2022-09-13 op fatal("%s: strndup", __func__);
792 b0a6bcf7 2022-09-13 op ret = symset(sym, val + 1, 1);
795 b0a6bcf7 2022-09-13 op return (ret);
799 b0a6bcf7 2022-09-13 op symget(const char *nam)
801 b0a6bcf7 2022-09-13 op struct sym *sym;
803 b0a6bcf7 2022-09-13 op TAILQ_FOREACH(sym, &symhead, entry) {
804 b0a6bcf7 2022-09-13 op if (strcmp(nam, sym->nam) == 0) {
805 b0a6bcf7 2022-09-13 op sym->used = 1;
806 b0a6bcf7 2022-09-13 op return (sym->val);
809 b0a6bcf7 2022-09-13 op return (NULL);
813 b0a6bcf7 2022-09-13 op getservice(const char *n)
815 b0a6bcf7 2022-09-13 op struct servent *s;
816 b0a6bcf7 2022-09-13 op const char *errstr;
817 b0a6bcf7 2022-09-13 op long long llval;
819 b0a6bcf7 2022-09-13 op llval = strtonum(n, 0, UINT16_MAX, &errstr);
820 b0a6bcf7 2022-09-13 op if (errstr) {
821 b0a6bcf7 2022-09-13 op s = getservbyname(n, "tcp");
822 b0a6bcf7 2022-09-13 op if (s == NULL)
823 b0a6bcf7 2022-09-13 op s = getservbyname(n, "udp");
824 b0a6bcf7 2022-09-13 op if (s == NULL)
826 b0a6bcf7 2022-09-13 op return (ntohs(s->s_port));
829 b0a6bcf7 2022-09-13 op return ((unsigned short)llval);