Blame


1 2c251c14 2020-01-15 tracey /*
2 c34ec417 2020-06-22 tracey * Copyright (c) 2019, 2020 Tracey Emery <tracey@openbsd.org>
3 c34ec417 2020-06-22 tracey * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
4 c34ec417 2020-06-22 tracey * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
5 2c251c14 2020-01-15 tracey * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
6 2c251c14 2020-01-15 tracey * Copyright (c) 2001 Markus Friedl. All rights reserved.
7 2c251c14 2020-01-15 tracey * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
8 2c251c14 2020-01-15 tracey * Copyright (c) 2001 Theo de Raadt. All rights reserved.
9 2c251c14 2020-01-15 tracey *
10 2c251c14 2020-01-15 tracey * Permission to use, copy, modify, and distribute this software for any
11 2c251c14 2020-01-15 tracey * purpose with or without fee is hereby granted, provided that the above
12 2c251c14 2020-01-15 tracey * copyright notice and this permission notice appear in all copies.
13 2c251c14 2020-01-15 tracey *
14 2c251c14 2020-01-15 tracey * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 2c251c14 2020-01-15 tracey * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 2c251c14 2020-01-15 tracey * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 2c251c14 2020-01-15 tracey * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 2c251c14 2020-01-15 tracey * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 2c251c14 2020-01-15 tracey * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 2c251c14 2020-01-15 tracey * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 2c251c14 2020-01-15 tracey */
22 2c251c14 2020-01-15 tracey
23 2c251c14 2020-01-15 tracey %{
24 2c251c14 2020-01-15 tracey #include <sys/types.h>
25 2c251c14 2020-01-15 tracey #include <sys/queue.h>
26 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
27 2c251c14 2020-01-15 tracey
28 2c251c14 2020-01-15 tracey #include <ctype.h>
29 2c251c14 2020-01-15 tracey #include <err.h>
30 2c251c14 2020-01-15 tracey #include <limits.h>
31 2c251c14 2020-01-15 tracey #include <stdarg.h>
32 2c251c14 2020-01-15 tracey #include <stdio.h>
33 cad0b9e8 2020-09-25 naddy #include <stdlib.h>
34 2c251c14 2020-01-15 tracey #include <string.h>
35 2c251c14 2020-01-15 tracey
36 c34ec417 2020-06-22 tracey #include "got_error.h"
37 2c251c14 2020-01-15 tracey #include "gotweb.h"
38 2c251c14 2020-01-15 tracey
39 2c251c14 2020-01-15 tracey TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
40 2c251c14 2020-01-15 tracey static struct file {
41 2c251c14 2020-01-15 tracey TAILQ_ENTRY(file) entry;
42 2c251c14 2020-01-15 tracey FILE *stream;
43 2c251c14 2020-01-15 tracey char *name;
44 c34ec417 2020-06-22 tracey size_t ungetpos;
45 c34ec417 2020-06-22 tracey size_t ungetsize;
46 c34ec417 2020-06-22 tracey u_char *ungetbuf;
47 c34ec417 2020-06-22 tracey int eof_reached;
48 2c251c14 2020-01-15 tracey int lineno;
49 2c251c14 2020-01-15 tracey } *file, *topfile;
50 c34ec417 2020-06-22 tracey static const struct got_error* pushfile(struct file**, const char *);
51 2c251c14 2020-01-15 tracey int popfile(void);
52 2c251c14 2020-01-15 tracey int yyparse(void);
53 2c251c14 2020-01-15 tracey int yylex(void);
54 2c251c14 2020-01-15 tracey int yyerror(const char *, ...)
55 2c251c14 2020-01-15 tracey __attribute__((__format__ (printf, 1, 2)))
56 2c251c14 2020-01-15 tracey __attribute__((__nonnull__ (1)));
57 2c251c14 2020-01-15 tracey int kw_cmp(const void *, const void *);
58 2c251c14 2020-01-15 tracey int lookup(char *);
59 c34ec417 2020-06-22 tracey int igetc(void);
60 2c251c14 2020-01-15 tracey int lgetc(int);
61 c34ec417 2020-06-22 tracey void lungetc(int);
62 2c251c14 2020-01-15 tracey int findeol(void);
63 2c251c14 2020-01-15 tracey
64 c34ec417 2020-06-22 tracey TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
65 c34ec417 2020-06-22 tracey struct sym {
66 c34ec417 2020-06-22 tracey TAILQ_ENTRY(sym) entry;
67 c34ec417 2020-06-22 tracey int used;
68 c34ec417 2020-06-22 tracey int persist;
69 c34ec417 2020-06-22 tracey char *nam;
70 c34ec417 2020-06-22 tracey char *val;
71 c34ec417 2020-06-22 tracey };
72 2c251c14 2020-01-15 tracey
73 c34ec417 2020-06-22 tracey int symset(const char *, const char *, int);
74 ef20f542 2022-06-26 thomas int cmdline_symset(char *);
75 c34ec417 2020-06-22 tracey char *symget(const char *);
76 2c251c14 2020-01-15 tracey
77 c34ec417 2020-06-22 tracey const struct got_error* gerror = NULL;
78 f71c0a3a 2020-06-23 tracey struct gotweb_config *gw_conf;
79 c34ec417 2020-06-22 tracey
80 2c251c14 2020-01-15 tracey typedef struct {
81 2c251c14 2020-01-15 tracey union {
82 c34ec417 2020-06-22 tracey int64_t number;
83 c34ec417 2020-06-22 tracey char *string;
84 2c251c14 2020-01-15 tracey } v;
85 2c251c14 2020-01-15 tracey int lineno;
86 2c251c14 2020-01-15 tracey } YYSTYPE;
87 2c251c14 2020-01-15 tracey
88 2c251c14 2020-01-15 tracey %}
89 2c251c14 2020-01-15 tracey
90 2c251c14 2020-01-15 tracey %token GOT_WWW_PATH GOT_MAX_REPOS GOT_SITE_NAME GOT_SITE_OWNER GOT_SITE_LINK
91 2c251c14 2020-01-15 tracey %token GOT_LOGO GOT_LOGO_URL GOT_SHOW_REPO_OWNER GOT_SHOW_REPO_AGE
92 2c251c14 2020-01-15 tracey %token GOT_SHOW_REPO_DESCRIPTION GOT_MAX_REPOS_DISPLAY GOT_REPOS_PATH
93 a03d32e0 2020-11-09 tracey %token GOT_MAX_COMMITS_DISPLAY ERROR GOT_SHOW_SITE_OWNER
94 2c251c14 2020-01-15 tracey %token GOT_SHOW_REPO_CLONEURL
95 c34ec417 2020-06-22 tracey %token <v.string> STRING
96 c34ec417 2020-06-22 tracey %token <v.number> NUMBER
97 c34ec417 2020-06-22 tracey %type <v.number> boolean
98 2c251c14 2020-01-15 tracey %%
99 2c251c14 2020-01-15 tracey
100 2c251c14 2020-01-15 tracey grammar : /* empty */
101 2c251c14 2020-01-15 tracey | grammar '\n'
102 2c251c14 2020-01-15 tracey | grammar main '\n'
103 2c251c14 2020-01-15 tracey ;
104 2c251c14 2020-01-15 tracey
105 c34ec417 2020-06-22 tracey boolean : STRING {
106 2c251c14 2020-01-15 tracey if (strcasecmp($1, "true") == 0 ||
107 a03d32e0 2020-11-09 tracey strcasecmp($1, "on") == 0 ||
108 2c251c14 2020-01-15 tracey strcasecmp($1, "yes") == 0)
109 2c251c14 2020-01-15 tracey $$ = 1;
110 2c251c14 2020-01-15 tracey else if (strcasecmp($1, "false") == 0 ||
111 2c251c14 2020-01-15 tracey strcasecmp($1, "off") == 0 ||
112 2c251c14 2020-01-15 tracey strcasecmp($1, "no") == 0)
113 2c251c14 2020-01-15 tracey $$ = 0;
114 2c251c14 2020-01-15 tracey else {
115 2c251c14 2020-01-15 tracey yyerror("invalid boolean value '%s'", $1);
116 2c251c14 2020-01-15 tracey free($1);
117 2c251c14 2020-01-15 tracey YYERROR;
118 2c251c14 2020-01-15 tracey }
119 2c251c14 2020-01-15 tracey free($1);
120 2c251c14 2020-01-15 tracey }
121 2c251c14 2020-01-15 tracey ;
122 2c251c14 2020-01-15 tracey main : GOT_REPOS_PATH STRING {
123 c2d7bc3f 2021-08-31 stsp gw_conf->got_repos_path = $2;
124 54415d85 2020-01-15 tracey }
125 9f6f3943 2020-09-24 tracey | GOT_WWW_PATH STRING {
126 c2d7bc3f 2021-08-31 stsp gw_conf->got_www_path = $2;
127 9f6f3943 2020-09-24 tracey }
128 2c251c14 2020-01-15 tracey | GOT_MAX_REPOS NUMBER {
129 2c251c14 2020-01-15 tracey if ($2 > 0)
130 f71c0a3a 2020-06-23 tracey gw_conf->got_max_repos = $2;
131 2c251c14 2020-01-15 tracey }
132 2c251c14 2020-01-15 tracey | GOT_SITE_NAME STRING {
133 c2d7bc3f 2021-08-31 stsp gw_conf->got_site_name = $2;
134 2c251c14 2020-01-15 tracey }
135 2c251c14 2020-01-15 tracey | GOT_SITE_OWNER STRING {
136 c2d7bc3f 2021-08-31 stsp gw_conf->got_site_owner = $2;
137 2c251c14 2020-01-15 tracey }
138 2c251c14 2020-01-15 tracey | GOT_SITE_LINK STRING {
139 c2d7bc3f 2021-08-31 stsp gw_conf->got_site_link = $2;
140 2c251c14 2020-01-15 tracey }
141 2c251c14 2020-01-15 tracey | GOT_LOGO STRING {
142 c2d7bc3f 2021-08-31 stsp gw_conf->got_logo = $2;
143 2c251c14 2020-01-15 tracey }
144 2c251c14 2020-01-15 tracey | GOT_LOGO_URL STRING {
145 c2d7bc3f 2021-08-31 stsp gw_conf->got_logo_url = $2;
146 2c251c14 2020-01-15 tracey }
147 2c251c14 2020-01-15 tracey | GOT_SHOW_SITE_OWNER boolean {
148 f71c0a3a 2020-06-23 tracey gw_conf->got_show_site_owner = $2;
149 2c251c14 2020-01-15 tracey }
150 2c251c14 2020-01-15 tracey | GOT_SHOW_REPO_OWNER boolean {
151 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_owner = $2;
152 2c251c14 2020-01-15 tracey }
153 c34ec417 2020-06-22 tracey | GOT_SHOW_REPO_AGE boolean {
154 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_age = $2;
155 c34ec417 2020-06-22 tracey }
156 2c251c14 2020-01-15 tracey | GOT_SHOW_REPO_DESCRIPTION boolean {
157 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_description = $2;
158 2c251c14 2020-01-15 tracey }
159 2c251c14 2020-01-15 tracey | GOT_SHOW_REPO_CLONEURL boolean {
160 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_cloneurl = $2;
161 2c251c14 2020-01-15 tracey }
162 2c251c14 2020-01-15 tracey | GOT_MAX_REPOS_DISPLAY NUMBER {
163 2c251c14 2020-01-15 tracey if ($2 > 0)
164 f71c0a3a 2020-06-23 tracey gw_conf->got_max_repos_display = $2;
165 2c251c14 2020-01-15 tracey }
166 2c251c14 2020-01-15 tracey | GOT_MAX_COMMITS_DISPLAY NUMBER {
167 2c251c14 2020-01-15 tracey if ($2 > 0)
168 f71c0a3a 2020-06-23 tracey gw_conf->got_max_commits_display = $2;
169 2c251c14 2020-01-15 tracey }
170 54415d85 2020-01-15 tracey ;
171 2c251c14 2020-01-15 tracey %%
172 2c251c14 2020-01-15 tracey
173 2c251c14 2020-01-15 tracey struct keywords {
174 2c251c14 2020-01-15 tracey const char *k_name;
175 2c251c14 2020-01-15 tracey int k_val;
176 2c251c14 2020-01-15 tracey };
177 2c251c14 2020-01-15 tracey
178 2c251c14 2020-01-15 tracey int
179 2c251c14 2020-01-15 tracey yyerror(const char *fmt, ...)
180 2c251c14 2020-01-15 tracey {
181 2c251c14 2020-01-15 tracey va_list ap;
182 c34ec417 2020-06-22 tracey char *msg;
183 c34ec417 2020-06-22 tracey char *err = NULL;
184 2c251c14 2020-01-15 tracey
185 2c251c14 2020-01-15 tracey va_start(ap, fmt);
186 c34ec417 2020-06-22 tracey if (vasprintf(&msg, fmt, ap) == -1) {
187 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("vasprintf");
188 c34ec417 2020-06-22 tracey return 0;
189 c34ec417 2020-06-22 tracey }
190 2c251c14 2020-01-15 tracey va_end(ap);
191 c34ec417 2020-06-22 tracey if (asprintf(&err, "%s:%d: %s", file->name, yylval.lineno, msg) == -1) {
192 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("asprintf");
193 c34ec417 2020-06-22 tracey return(0);
194 c34ec417 2020-06-22 tracey }
195 c2d7bc3f 2021-08-31 stsp gerror = got_error_msg(GOT_ERR_PARSE_CONFIG, err);
196 2c251c14 2020-01-15 tracey free(msg);
197 c34ec417 2020-06-22 tracey return(0);
198 2c251c14 2020-01-15 tracey }
199 2c251c14 2020-01-15 tracey
200 2c251c14 2020-01-15 tracey int
201 2c251c14 2020-01-15 tracey kw_cmp(const void *k, const void *e)
202 2c251c14 2020-01-15 tracey {
203 2c251c14 2020-01-15 tracey return (strcmp(k, ((const struct keywords *)e)->k_name));
204 2c251c14 2020-01-15 tracey }
205 2c251c14 2020-01-15 tracey
206 2c251c14 2020-01-15 tracey int
207 2c251c14 2020-01-15 tracey lookup(char *s)
208 2c251c14 2020-01-15 tracey {
209 c34ec417 2020-06-22 tracey /* This has to be sorted always. */
210 2c251c14 2020-01-15 tracey static const struct keywords keywords[] = {
211 2c251c14 2020-01-15 tracey { "got_logo", GOT_LOGO },
212 2c251c14 2020-01-15 tracey { "got_logo_url", GOT_LOGO_URL },
213 2c251c14 2020-01-15 tracey { "got_max_commits_display", GOT_MAX_COMMITS_DISPLAY },
214 2c251c14 2020-01-15 tracey { "got_max_repos", GOT_MAX_REPOS },
215 2c251c14 2020-01-15 tracey { "got_max_repos_display", GOT_MAX_REPOS_DISPLAY },
216 2c251c14 2020-01-15 tracey { "got_repos_path", GOT_REPOS_PATH },
217 2c251c14 2020-01-15 tracey { "got_show_repo_age", GOT_SHOW_REPO_AGE },
218 2c251c14 2020-01-15 tracey { "got_show_repo_cloneurl", GOT_SHOW_REPO_CLONEURL },
219 2c251c14 2020-01-15 tracey { "got_show_repo_description", GOT_SHOW_REPO_DESCRIPTION },
220 2c251c14 2020-01-15 tracey { "got_show_repo_owner", GOT_SHOW_REPO_OWNER },
221 2c251c14 2020-01-15 tracey { "got_show_site_owner", GOT_SHOW_SITE_OWNER },
222 2c251c14 2020-01-15 tracey { "got_site_link", GOT_SITE_LINK },
223 2c251c14 2020-01-15 tracey { "got_site_name", GOT_SITE_NAME },
224 2c251c14 2020-01-15 tracey { "got_site_owner", GOT_SITE_OWNER },
225 9f6f3943 2020-09-24 tracey { "got_www_path", GOT_WWW_PATH },
226 2c251c14 2020-01-15 tracey };
227 2c251c14 2020-01-15 tracey const struct keywords *p;
228 2c251c14 2020-01-15 tracey
229 2c251c14 2020-01-15 tracey p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
230 2c251c14 2020-01-15 tracey sizeof(keywords[0]), kw_cmp);
231 2c251c14 2020-01-15 tracey
232 2c251c14 2020-01-15 tracey if (p)
233 2c251c14 2020-01-15 tracey return (p->k_val);
234 2c251c14 2020-01-15 tracey else
235 2c251c14 2020-01-15 tracey return (STRING);
236 2c251c14 2020-01-15 tracey }
237 2c251c14 2020-01-15 tracey
238 c34ec417 2020-06-22 tracey #define START_EXPAND 1
239 c34ec417 2020-06-22 tracey #define DONE_EXPAND 2
240 2c251c14 2020-01-15 tracey
241 c34ec417 2020-06-22 tracey static int expanding;
242 2c251c14 2020-01-15 tracey
243 2c251c14 2020-01-15 tracey int
244 c34ec417 2020-06-22 tracey igetc(void)
245 2c251c14 2020-01-15 tracey {
246 c34ec417 2020-06-22 tracey int c;
247 2c251c14 2020-01-15 tracey
248 c34ec417 2020-06-22 tracey while (1) {
249 c34ec417 2020-06-22 tracey if (file->ungetpos > 0)
250 c34ec417 2020-06-22 tracey c = file->ungetbuf[--file->ungetpos];
251 c34ec417 2020-06-22 tracey else
252 c34ec417 2020-06-22 tracey c = getc(file->stream);
253 c34ec417 2020-06-22 tracey
254 c34ec417 2020-06-22 tracey if (c == START_EXPAND)
255 c34ec417 2020-06-22 tracey expanding = 1;
256 c34ec417 2020-06-22 tracey else if (c == DONE_EXPAND)
257 c34ec417 2020-06-22 tracey expanding = 0;
258 c34ec417 2020-06-22 tracey else
259 c34ec417 2020-06-22 tracey break;
260 2c251c14 2020-01-15 tracey }
261 c34ec417 2020-06-22 tracey return (c);
262 c34ec417 2020-06-22 tracey }
263 2c251c14 2020-01-15 tracey
264 c34ec417 2020-06-22 tracey int
265 c34ec417 2020-06-22 tracey lgetc(int quotec)
266 c34ec417 2020-06-22 tracey {
267 c34ec417 2020-06-22 tracey int c, next;
268 2c251c14 2020-01-15 tracey
269 2c251c14 2020-01-15 tracey if (quotec) {
270 c34ec417 2020-06-22 tracey if ((c = igetc()) == EOF) {
271 2c251c14 2020-01-15 tracey yyerror("reached end of file while parsing "
272 2c251c14 2020-01-15 tracey "quoted string");
273 2c251c14 2020-01-15 tracey if (file == topfile || popfile() == EOF)
274 2c251c14 2020-01-15 tracey return (EOF);
275 2c251c14 2020-01-15 tracey return (quotec);
276 2c251c14 2020-01-15 tracey }
277 2c251c14 2020-01-15 tracey return (c);
278 2c251c14 2020-01-15 tracey }
279 2c251c14 2020-01-15 tracey
280 c34ec417 2020-06-22 tracey while ((c = igetc()) == '\\') {
281 c34ec417 2020-06-22 tracey next = igetc();
282 2c251c14 2020-01-15 tracey if (next != '\n') {
283 2c251c14 2020-01-15 tracey c = next;
284 2c251c14 2020-01-15 tracey break;
285 2c251c14 2020-01-15 tracey }
286 2c251c14 2020-01-15 tracey yylval.lineno = file->lineno;
287 2c251c14 2020-01-15 tracey file->lineno++;
288 2c251c14 2020-01-15 tracey }
289 2c251c14 2020-01-15 tracey
290 c34ec417 2020-06-22 tracey if (c == EOF) {
291 c34ec417 2020-06-22 tracey /*
292 c34ec417 2020-06-22 tracey * Fake EOL when hit EOF for the first time. This gets line
293 c34ec417 2020-06-22 tracey * count right if last line in included file is syntactically
294 c34ec417 2020-06-22 tracey * invalid and has no newline.
295 c34ec417 2020-06-22 tracey */
296 c34ec417 2020-06-22 tracey if (file->eof_reached == 0) {
297 c34ec417 2020-06-22 tracey file->eof_reached = 1;
298 c34ec417 2020-06-22 tracey return ('\n');
299 c34ec417 2020-06-22 tracey }
300 c34ec417 2020-06-22 tracey while (c == EOF) {
301 c34ec417 2020-06-22 tracey if (file == topfile || popfile() == EOF)
302 c34ec417 2020-06-22 tracey return (EOF);
303 c34ec417 2020-06-22 tracey c = igetc();
304 c34ec417 2020-06-22 tracey }
305 2c251c14 2020-01-15 tracey }
306 2c251c14 2020-01-15 tracey return (c);
307 2c251c14 2020-01-15 tracey }
308 2c251c14 2020-01-15 tracey
309 c34ec417 2020-06-22 tracey void
310 2c251c14 2020-01-15 tracey lungetc(int c)
311 2c251c14 2020-01-15 tracey {
312 2c251c14 2020-01-15 tracey if (c == EOF)
313 c34ec417 2020-06-22 tracey return;
314 c34ec417 2020-06-22 tracey
315 c34ec417 2020-06-22 tracey if (file->ungetpos >= file->ungetsize) {
316 c34ec417 2020-06-22 tracey void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
317 c34ec417 2020-06-22 tracey if (p == NULL)
318 c34ec417 2020-06-22 tracey err(1, "%s", __func__);
319 c34ec417 2020-06-22 tracey file->ungetbuf = p;
320 c34ec417 2020-06-22 tracey file->ungetsize *= 2;
321 2c251c14 2020-01-15 tracey }
322 c34ec417 2020-06-22 tracey file->ungetbuf[file->ungetpos++] = c;
323 2c251c14 2020-01-15 tracey }
324 2c251c14 2020-01-15 tracey
325 2c251c14 2020-01-15 tracey int
326 2c251c14 2020-01-15 tracey findeol(void)
327 2c251c14 2020-01-15 tracey {
328 2c251c14 2020-01-15 tracey int c;
329 2c251c14 2020-01-15 tracey
330 c34ec417 2020-06-22 tracey /* Skip to either EOF or the first real EOL. */
331 2c251c14 2020-01-15 tracey while (1) {
332 c34ec417 2020-06-22 tracey c = lgetc(0);
333 2c251c14 2020-01-15 tracey if (c == '\n') {
334 2c251c14 2020-01-15 tracey file->lineno++;
335 2c251c14 2020-01-15 tracey break;
336 2c251c14 2020-01-15 tracey }
337 2c251c14 2020-01-15 tracey if (c == EOF)
338 2c251c14 2020-01-15 tracey break;
339 2c251c14 2020-01-15 tracey }
340 2c251c14 2020-01-15 tracey return (ERROR);
341 2c251c14 2020-01-15 tracey }
342 2c251c14 2020-01-15 tracey
343 2c251c14 2020-01-15 tracey int
344 2c251c14 2020-01-15 tracey yylex(void)
345 2c251c14 2020-01-15 tracey {
346 d7a84292 2021-09-30 thomas char buf[8096];
347 d7a84292 2021-09-30 thomas char *p, *val;
348 d7a84292 2021-09-30 thomas int quotec, next, c;
349 d7a84292 2021-09-30 thomas int token;
350 2c251c14 2020-01-15 tracey
351 c34ec417 2020-06-22 tracey top:
352 2c251c14 2020-01-15 tracey p = buf;
353 2c251c14 2020-01-15 tracey while ((c = lgetc(0)) == ' ' || c == '\t')
354 2c251c14 2020-01-15 tracey ; /* nothing */
355 2c251c14 2020-01-15 tracey
356 2c251c14 2020-01-15 tracey yylval.lineno = file->lineno;
357 2c251c14 2020-01-15 tracey if (c == '#')
358 2c251c14 2020-01-15 tracey while ((c = lgetc(0)) != '\n' && c != EOF)
359 2c251c14 2020-01-15 tracey ; /* nothing */
360 c34ec417 2020-06-22 tracey if (c == '$' && !expanding) {
361 c34ec417 2020-06-22 tracey while (1) {
362 c34ec417 2020-06-22 tracey if ((c = lgetc(0)) == EOF)
363 c34ec417 2020-06-22 tracey return (0);
364 2c251c14 2020-01-15 tracey
365 c34ec417 2020-06-22 tracey if (p + 1 >= buf + sizeof(buf) - 1) {
366 c34ec417 2020-06-22 tracey yyerror("string too long");
367 c34ec417 2020-06-22 tracey return (findeol());
368 c34ec417 2020-06-22 tracey }
369 c34ec417 2020-06-22 tracey if (isalnum(c) || c == '_') {
370 c34ec417 2020-06-22 tracey *p++ = c;
371 c34ec417 2020-06-22 tracey continue;
372 c34ec417 2020-06-22 tracey }
373 c34ec417 2020-06-22 tracey *p = '\0';
374 c34ec417 2020-06-22 tracey lungetc(c);
375 c34ec417 2020-06-22 tracey break;
376 c34ec417 2020-06-22 tracey }
377 c34ec417 2020-06-22 tracey val = symget(buf);
378 c34ec417 2020-06-22 tracey if (val == NULL) {
379 c34ec417 2020-06-22 tracey yyerror("macro '%s' not defined", buf);
380 c34ec417 2020-06-22 tracey return (findeol());
381 c34ec417 2020-06-22 tracey }
382 c34ec417 2020-06-22 tracey p = val + strlen(val) - 1;
383 c34ec417 2020-06-22 tracey lungetc(DONE_EXPAND);
384 c34ec417 2020-06-22 tracey while (p >= val) {
385 bb27d0d1 2021-10-15 thomas lungetc((unsigned char)*p);
386 c34ec417 2020-06-22 tracey p--;
387 c34ec417 2020-06-22 tracey }
388 c34ec417 2020-06-22 tracey lungetc(START_EXPAND);
389 c34ec417 2020-06-22 tracey goto top;
390 c34ec417 2020-06-22 tracey }
391 c34ec417 2020-06-22 tracey
392 2c251c14 2020-01-15 tracey switch (c) {
393 2c251c14 2020-01-15 tracey case '\'':
394 2c251c14 2020-01-15 tracey case '"':
395 2c251c14 2020-01-15 tracey quotec = c;
396 2c251c14 2020-01-15 tracey while (1) {
397 2c251c14 2020-01-15 tracey if ((c = lgetc(quotec)) == EOF)
398 2c251c14 2020-01-15 tracey return (0);
399 2c251c14 2020-01-15 tracey if (c == '\n') {
400 2c251c14 2020-01-15 tracey file->lineno++;
401 2c251c14 2020-01-15 tracey continue;
402 2c251c14 2020-01-15 tracey } else if (c == '\\') {
403 2c251c14 2020-01-15 tracey if ((next = lgetc(quotec)) == EOF)
404 2c251c14 2020-01-15 tracey return (0);
405 c34ec417 2020-06-22 tracey if (next == quotec || c == ' ' || c == '\t')
406 2c251c14 2020-01-15 tracey c = next;
407 2c251c14 2020-01-15 tracey else if (next == '\n') {
408 2c251c14 2020-01-15 tracey file->lineno++;
409 2c251c14 2020-01-15 tracey continue;
410 2c251c14 2020-01-15 tracey } else
411 2c251c14 2020-01-15 tracey lungetc(next);
412 2c251c14 2020-01-15 tracey } else if (c == quotec) {
413 2c251c14 2020-01-15 tracey *p = '\0';
414 2c251c14 2020-01-15 tracey break;
415 2c251c14 2020-01-15 tracey } else if (c == '\0') {
416 2c251c14 2020-01-15 tracey yyerror("syntax error");
417 2c251c14 2020-01-15 tracey return (findeol());
418 2c251c14 2020-01-15 tracey }
419 2c251c14 2020-01-15 tracey if (p + 1 >= buf + sizeof(buf) - 1) {
420 2c251c14 2020-01-15 tracey yyerror("string too long");
421 2c251c14 2020-01-15 tracey return (findeol());
422 2c251c14 2020-01-15 tracey }
423 2c251c14 2020-01-15 tracey *p++ = c;
424 2c251c14 2020-01-15 tracey }
425 2c251c14 2020-01-15 tracey yylval.v.string = strdup(buf);
426 2c251c14 2020-01-15 tracey if (yylval.v.string == NULL)
427 c34ec417 2020-06-22 tracey err(1, "%s", __func__);
428 2c251c14 2020-01-15 tracey return (STRING);
429 2c251c14 2020-01-15 tracey }
430 2c251c14 2020-01-15 tracey
431 2c251c14 2020-01-15 tracey #define allowed_to_end_number(x) \
432 2c251c14 2020-01-15 tracey (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
433 2c251c14 2020-01-15 tracey
434 2c251c14 2020-01-15 tracey if (c == '-' || isdigit(c)) {
435 2c251c14 2020-01-15 tracey do {
436 2c251c14 2020-01-15 tracey *p++ = c;
437 ccd081e7 2021-09-30 thomas if ((size_t)(p-buf) >= sizeof(buf)) {
438 2c251c14 2020-01-15 tracey yyerror("string too long");
439 2c251c14 2020-01-15 tracey return (findeol());
440 2c251c14 2020-01-15 tracey }
441 2c251c14 2020-01-15 tracey } while ((c = lgetc(0)) != EOF && isdigit(c));
442 2c251c14 2020-01-15 tracey lungetc(c);
443 2c251c14 2020-01-15 tracey if (p == buf + 1 && buf[0] == '-')
444 2c251c14 2020-01-15 tracey goto nodigits;
445 2c251c14 2020-01-15 tracey if (c == EOF || allowed_to_end_number(c)) {
446 2c251c14 2020-01-15 tracey const char *errstr = NULL;
447 2c251c14 2020-01-15 tracey
448 2c251c14 2020-01-15 tracey *p = '\0';
449 2c251c14 2020-01-15 tracey yylval.v.number = strtonum(buf, LLONG_MIN,
450 2c251c14 2020-01-15 tracey LLONG_MAX, &errstr);
451 2c251c14 2020-01-15 tracey if (errstr) {
452 2c251c14 2020-01-15 tracey yyerror("\"%s\" invalid number: %s",
453 2c251c14 2020-01-15 tracey buf, errstr);
454 2c251c14 2020-01-15 tracey return (findeol());
455 2c251c14 2020-01-15 tracey }
456 2c251c14 2020-01-15 tracey return (NUMBER);
457 2c251c14 2020-01-15 tracey } else {
458 2c251c14 2020-01-15 tracey nodigits:
459 2c251c14 2020-01-15 tracey while (p > buf + 1)
460 bb27d0d1 2021-10-15 thomas lungetc((unsigned char)*--p);
461 bb27d0d1 2021-10-15 thomas c = (unsigned char)*--p;
462 2c251c14 2020-01-15 tracey if (c == '-')
463 2c251c14 2020-01-15 tracey return (c);
464 2c251c14 2020-01-15 tracey }
465 2c251c14 2020-01-15 tracey }
466 2c251c14 2020-01-15 tracey
467 2c251c14 2020-01-15 tracey #define allowed_in_string(x) \
468 2c251c14 2020-01-15 tracey (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
469 c34ec417 2020-06-22 tracey x != '{' && x != '}' && \
470 c34ec417 2020-06-22 tracey x != '!' && x != '=' && x != '#' && \
471 2c251c14 2020-01-15 tracey x != ','))
472 2c251c14 2020-01-15 tracey
473 c34ec417 2020-06-22 tracey if (isalnum(c) || c == ':' || c == '_') {
474 2c251c14 2020-01-15 tracey do {
475 2c251c14 2020-01-15 tracey *p++ = c;
476 ccd081e7 2021-09-30 thomas if ((size_t)(p-buf) >= sizeof(buf)) {
477 2c251c14 2020-01-15 tracey yyerror("string too long");
478 2c251c14 2020-01-15 tracey return (findeol());
479 2c251c14 2020-01-15 tracey }
480 2c251c14 2020-01-15 tracey } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
481 2c251c14 2020-01-15 tracey lungetc(c);
482 2c251c14 2020-01-15 tracey *p = '\0';
483 2c251c14 2020-01-15 tracey if ((token = lookup(buf)) == STRING)
484 2c251c14 2020-01-15 tracey if ((yylval.v.string = strdup(buf)) == NULL)
485 c34ec417 2020-06-22 tracey err(1, "%s", __func__);
486 2c251c14 2020-01-15 tracey return (token);
487 2c251c14 2020-01-15 tracey }
488 2c251c14 2020-01-15 tracey if (c == '\n') {
489 2c251c14 2020-01-15 tracey yylval.lineno = file->lineno;
490 2c251c14 2020-01-15 tracey file->lineno++;
491 2c251c14 2020-01-15 tracey }
492 2c251c14 2020-01-15 tracey if (c == EOF)
493 2c251c14 2020-01-15 tracey return (0);
494 2c251c14 2020-01-15 tracey return (c);
495 2c251c14 2020-01-15 tracey }
496 2c251c14 2020-01-15 tracey
497 c34ec417 2020-06-22 tracey static const struct got_error*
498 c34ec417 2020-06-22 tracey pushfile(struct file **nfile, const char *name)
499 2c251c14 2020-01-15 tracey {
500 c34ec417 2020-06-22 tracey const struct got_error* error = NULL;
501 2c251c14 2020-01-15 tracey
502 c34ec417 2020-06-22 tracey if (((*nfile) = calloc(1, sizeof(struct file))) == NULL)
503 c34ec417 2020-06-22 tracey return got_error_from_errno2(__func__, "calloc");
504 c34ec417 2020-06-22 tracey if (((*nfile)->name = strdup(name)) == NULL) {
505 2c251c14 2020-01-15 tracey free(nfile);
506 c34ec417 2020-06-22 tracey return got_error_from_errno2(__func__, "strdup");
507 2c251c14 2020-01-15 tracey }
508 c56c5d8a 2021-12-31 thomas if (((*nfile)->stream = fopen((*nfile)->name, "re")) == NULL) {
509 c34ec417 2020-06-22 tracey char *msg = NULL;
510 c34ec417 2020-06-22 tracey if (asprintf(&msg, "%s", (*nfile)->name) == -1)
511 c34ec417 2020-06-22 tracey return got_error_from_errno("asprintf");
512 c34ec417 2020-06-22 tracey error = got_error_msg(GOT_ERR_NO_CONFIG_FILE, msg);
513 c34ec417 2020-06-22 tracey free((*nfile)->name);
514 c34ec417 2020-06-22 tracey free((*nfile));
515 c34ec417 2020-06-22 tracey free(msg);
516 c34ec417 2020-06-22 tracey return error;
517 2c251c14 2020-01-15 tracey }
518 c34ec417 2020-06-22 tracey (*nfile)->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
519 c34ec417 2020-06-22 tracey (*nfile)->ungetsize = 16;
520 c34ec417 2020-06-22 tracey (*nfile)->ungetbuf = malloc((*nfile)->ungetsize);
521 c34ec417 2020-06-22 tracey if ((*nfile)->ungetbuf == NULL) {
522 c34ec417 2020-06-22 tracey fclose((*nfile)->stream);
523 c34ec417 2020-06-22 tracey free((*nfile)->name);
524 c34ec417 2020-06-22 tracey free((*nfile));
525 c34ec417 2020-06-22 tracey return got_error_from_errno2(__func__, "malloc");
526 c34ec417 2020-06-22 tracey }
527 c34ec417 2020-06-22 tracey TAILQ_INSERT_TAIL(&files, (*nfile), entry);
528 c34ec417 2020-06-22 tracey return error;
529 2c251c14 2020-01-15 tracey }
530 2c251c14 2020-01-15 tracey
531 2c251c14 2020-01-15 tracey int
532 2c251c14 2020-01-15 tracey popfile(void)
533 2c251c14 2020-01-15 tracey {
534 c34ec417 2020-06-22 tracey struct file *prev = NULL;
535 2c251c14 2020-01-15 tracey
536 2c251c14 2020-01-15 tracey TAILQ_REMOVE(&files, file, entry);
537 2c251c14 2020-01-15 tracey fclose(file->stream);
538 2c251c14 2020-01-15 tracey free(file->name);
539 c34ec417 2020-06-22 tracey free(file->ungetbuf);
540 2c251c14 2020-01-15 tracey free(file);
541 2c251c14 2020-01-15 tracey file = prev;
542 2c251c14 2020-01-15 tracey return (file ? 0 : EOF);
543 2c251c14 2020-01-15 tracey }
544 2c251c14 2020-01-15 tracey
545 2c251c14 2020-01-15 tracey const struct got_error*
546 c34ec417 2020-06-22 tracey parse_gotweb_config(struct gotweb_config **gconf, const char *filename)
547 2c251c14 2020-01-15 tracey {
548 f71c0a3a 2020-06-23 tracey gw_conf = malloc(sizeof(struct gotweb_config));
549 f71c0a3a 2020-06-23 tracey if (gw_conf == NULL) {
550 f71c0a3a 2020-06-23 tracey gerror = got_error_from_errno("malloc");
551 f71c0a3a 2020-06-23 tracey goto done;
552 f71c0a3a 2020-06-23 tracey }
553 f71c0a3a 2020-06-23 tracey gw_conf->got_repos_path = strdup(D_GOTPATH);
554 f71c0a3a 2020-06-23 tracey if (gw_conf->got_repos_path == NULL) {
555 9f6f3943 2020-09-24 tracey gerror = got_error_from_errno("strdup");
556 9f6f3943 2020-09-24 tracey goto done;
557 9f6f3943 2020-09-24 tracey }
558 9f6f3943 2020-09-24 tracey gw_conf->got_www_path = strdup(D_GOTWWW);
559 9f6f3943 2020-09-24 tracey if (gw_conf->got_www_path == NULL) {
560 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
561 2c251c14 2020-01-15 tracey goto done;
562 2c251c14 2020-01-15 tracey }
563 f71c0a3a 2020-06-23 tracey gw_conf->got_site_name = strdup(D_SITENAME);
564 f71c0a3a 2020-06-23 tracey if (gw_conf->got_site_name == NULL) {
565 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
566 c34ec417 2020-06-22 tracey goto done;
567 c34ec417 2020-06-22 tracey }
568 f71c0a3a 2020-06-23 tracey gw_conf->got_site_owner = strdup(D_SITEOWNER);
569 f71c0a3a 2020-06-23 tracey if (gw_conf->got_site_owner == NULL) {
570 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
571 c34ec417 2020-06-22 tracey goto done;
572 c34ec417 2020-06-22 tracey }
573 f71c0a3a 2020-06-23 tracey gw_conf->got_site_link = strdup(D_SITELINK);
574 f71c0a3a 2020-06-23 tracey if (gw_conf->got_site_link == NULL) {
575 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
576 c34ec417 2020-06-22 tracey goto done;
577 c34ec417 2020-06-22 tracey }
578 f71c0a3a 2020-06-23 tracey gw_conf->got_logo = strdup(D_GOTLOGO);
579 f71c0a3a 2020-06-23 tracey if (gw_conf->got_logo == NULL) {
580 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
581 c34ec417 2020-06-22 tracey goto done;
582 c34ec417 2020-06-22 tracey }
583 f71c0a3a 2020-06-23 tracey gw_conf->got_logo_url = strdup(D_GOTURL);
584 f71c0a3a 2020-06-23 tracey if (gw_conf->got_logo_url == NULL) {
585 c34ec417 2020-06-22 tracey gerror = got_error_from_errno("strdup");
586 c34ec417 2020-06-22 tracey goto done;
587 c34ec417 2020-06-22 tracey }
588 f71c0a3a 2020-06-23 tracey gw_conf->got_show_site_owner = D_SHOWSOWNER;
589 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_owner = D_SHOWROWNER;
590 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_age = D_SHOWAGE;
591 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_description = D_SHOWDESC;
592 f71c0a3a 2020-06-23 tracey gw_conf->got_show_repo_cloneurl = D_SHOWURL;
593 f71c0a3a 2020-06-23 tracey gw_conf->got_max_repos = D_MAXREPO;
594 f71c0a3a 2020-06-23 tracey gw_conf->got_max_repos_display = D_MAXREPODISP;
595 f71c0a3a 2020-06-23 tracey gw_conf->got_max_commits_display = D_MAXCOMMITDISP;
596 c34ec417 2020-06-22 tracey
597 c34ec417 2020-06-22 tracey /*
598 c34ec417 2020-06-22 tracey * We don't require that the gotweb config file exists
599 c34ec417 2020-06-22 tracey * So reset gerror if it doesn't exist and goto done.
600 c34ec417 2020-06-22 tracey */
601 c34ec417 2020-06-22 tracey gerror = pushfile(&file, filename);
602 c34ec417 2020-06-22 tracey if (gerror && gerror->code == GOT_ERR_NO_CONFIG_FILE) {
603 c34ec417 2020-06-22 tracey gerror = NULL;
604 c34ec417 2020-06-22 tracey goto done;
605 c34ec417 2020-06-22 tracey } else if (gerror)
606 c34ec417 2020-06-22 tracey return gerror;
607 2c251c14 2020-01-15 tracey topfile = file;
608 2c251c14 2020-01-15 tracey
609 2c251c14 2020-01-15 tracey yyparse();
610 2c251c14 2020-01-15 tracey popfile();
611 2c251c14 2020-01-15 tracey done:
612 f71c0a3a 2020-06-23 tracey *gconf = gw_conf;
613 c34ec417 2020-06-22 tracey return gerror;
614 2c251c14 2020-01-15 tracey }
615 c34ec417 2020-06-22 tracey
616 c34ec417 2020-06-22 tracey int
617 c34ec417 2020-06-22 tracey symset(const char *nam, const char *val, int persist)
618 c34ec417 2020-06-22 tracey {
619 c34ec417 2020-06-22 tracey struct sym *sym;
620 c34ec417 2020-06-22 tracey
621 c34ec417 2020-06-22 tracey TAILQ_FOREACH(sym, &symhead, entry) {
622 c34ec417 2020-06-22 tracey if (strcmp(nam, sym->nam) == 0)
623 c34ec417 2020-06-22 tracey break;
624 c34ec417 2020-06-22 tracey }
625 c34ec417 2020-06-22 tracey
626 c34ec417 2020-06-22 tracey if (sym != NULL) {
627 c34ec417 2020-06-22 tracey if (sym->persist == 1)
628 c34ec417 2020-06-22 tracey return (0);
629 c34ec417 2020-06-22 tracey else {
630 c34ec417 2020-06-22 tracey free(sym->nam);
631 c34ec417 2020-06-22 tracey free(sym->val);
632 c34ec417 2020-06-22 tracey TAILQ_REMOVE(&symhead, sym, entry);
633 c34ec417 2020-06-22 tracey free(sym);
634 c34ec417 2020-06-22 tracey }
635 c34ec417 2020-06-22 tracey }
636 c34ec417 2020-06-22 tracey if ((sym = calloc(1, sizeof(*sym))) == NULL)
637 c34ec417 2020-06-22 tracey return (-1);
638 c34ec417 2020-06-22 tracey
639 c34ec417 2020-06-22 tracey sym->nam = strdup(nam);
640 c34ec417 2020-06-22 tracey if (sym->nam == NULL) {
641 c34ec417 2020-06-22 tracey free(sym);
642 c34ec417 2020-06-22 tracey return (-1);
643 c34ec417 2020-06-22 tracey }
644 c34ec417 2020-06-22 tracey sym->val = strdup(val);
645 c34ec417 2020-06-22 tracey if (sym->val == NULL) {
646 c34ec417 2020-06-22 tracey free(sym->nam);
647 c34ec417 2020-06-22 tracey free(sym);
648 c34ec417 2020-06-22 tracey return (-1);
649 c34ec417 2020-06-22 tracey }
650 c34ec417 2020-06-22 tracey sym->used = 0;
651 c34ec417 2020-06-22 tracey sym->persist = persist;
652 c34ec417 2020-06-22 tracey TAILQ_INSERT_TAIL(&symhead, sym, entry);
653 c34ec417 2020-06-22 tracey return (0);
654 c34ec417 2020-06-22 tracey }
655 c34ec417 2020-06-22 tracey
656 c34ec417 2020-06-22 tracey int
657 c34ec417 2020-06-22 tracey cmdline_symset(char *s)
658 c34ec417 2020-06-22 tracey {
659 c34ec417 2020-06-22 tracey char *sym, *val;
660 c34ec417 2020-06-22 tracey int ret;
661 c34ec417 2020-06-22 tracey size_t len;
662 c34ec417 2020-06-22 tracey
663 c34ec417 2020-06-22 tracey if ((val = strrchr(s, '=')) == NULL)
664 c34ec417 2020-06-22 tracey return (-1);
665 c34ec417 2020-06-22 tracey
666 c34ec417 2020-06-22 tracey len = strlen(s) - strlen(val) + 1;
667 c34ec417 2020-06-22 tracey if ((sym = malloc(len)) == NULL)
668 c34ec417 2020-06-22 tracey errx(1, "cmdline_symset: malloc");
669 c34ec417 2020-06-22 tracey
670 c34ec417 2020-06-22 tracey strlcpy(sym, s, len);
671 c34ec417 2020-06-22 tracey
672 c34ec417 2020-06-22 tracey ret = symset(sym, val + 1, 1);
673 c34ec417 2020-06-22 tracey free(sym);
674 c34ec417 2020-06-22 tracey
675 c34ec417 2020-06-22 tracey return (ret);
676 c34ec417 2020-06-22 tracey }
677 c34ec417 2020-06-22 tracey
678 c34ec417 2020-06-22 tracey char *
679 c34ec417 2020-06-22 tracey symget(const char *nam)
680 c34ec417 2020-06-22 tracey {
681 c34ec417 2020-06-22 tracey struct sym *sym;
682 c34ec417 2020-06-22 tracey
683 c34ec417 2020-06-22 tracey TAILQ_FOREACH(sym, &symhead, entry) {
684 c34ec417 2020-06-22 tracey if (strcmp(nam, sym->nam) == 0) {
685 c34ec417 2020-06-22 tracey sym->used = 1;
686 c34ec417 2020-06-22 tracey return (sym->val);
687 c34ec417 2020-06-22 tracey }
688 c34ec417 2020-06-22 tracey }
689 c34ec417 2020-06-22 tracey return (NULL);
690 c34ec417 2020-06-22 tracey }