regress: use seq instead of jot
[got-portable.git] / gotwebd / gotwebd.h
blob207c4dbc424493d3ff719acc1447d3cad5906547
1 /*
2 * Copyright (c) 2016, 2019, 2020-2022 Tracey Emery <tracey@traceyemery.net>
3 * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
4 * Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
5 * Copyright (c) 2013 Florian Obser <florian@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <netinet/in.h>
21 #include <net/if.h>
22 #include <sys/queue.h>
24 #include <limits.h>
25 #include <stdio.h>
27 #include "tmpl.h"
29 #ifdef DEBUG
30 #define dprintf(x...) do { log_debug(x); } while(0)
31 #else
32 #define dprintf(x...)
33 #endif /* DEBUG */
35 #ifndef nitems
36 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
37 #endif
39 /* GOTWEBD DEFAULTS */
40 #define GOTWEBD_CONF "/etc/gotwebd.conf"
42 #define GOTWEBD_USER "www"
44 #define GOTWEBD_MAXDESCRSZ 1024
45 #define GOTWEBD_MAXCLONEURLSZ 1024
46 #define GOTWEBD_CACHESIZE 1024
47 #define GOTWEBD_MAXCLIENTS 1024
48 #define GOTWEBD_MAXTEXT 511
49 #define GOTWEBD_MAXNAME 64
50 #define GOTWEBD_MAXPORT 6
51 #define GOTWEBD_NUMPROC 3
52 #define GOTWEBD_SOCK_FILENO 3
54 #define PROC_MAX_INSTANCES 32
56 /* GOTWEB DEFAULTS */
57 #define MAX_QUERYSTRING 2048
58 #define MAX_DOCUMENT_URI 255
59 #define MAX_SERVER_NAME 255
61 #define GOTWEB_GIT_DIR ".git"
63 #define D_HTTPD_CHROOT "/var/www"
64 #define D_UNIX_SOCKET "/run/gotweb.sock"
65 #define D_FCGI_PORT "9000"
66 #define D_GOTPATH "/got/public"
67 #define D_SITENAME "Gotweb"
68 #define D_SITEOWNER "Got Owner"
69 #define D_SITELINK "Repos"
70 #define D_GOTLOGO "got.png"
71 #define D_GOTURL "https://gameoftrees.org"
72 #define D_GOTWEBCSS "gotweb.css"
74 #define D_SHOWROWNER 1
75 #define D_SHOWSOWNER 1
76 #define D_SHOWAGE 1
77 #define D_SHOWDESC 1
78 #define D_SHOWURL 1
79 #define D_RESPECTEXPORTOK 0
80 #define D_MAXREPODISP 25
81 #define D_MAXSLCOMMDISP 10
82 #define D_MAXCOMMITDISP 25
83 #define D_MAXSLTAGDISP 3
85 #define BUF 8192
87 #define TIMEOUT_DEFAULT 120
89 #define FCGI_CONTENT_SIZE 65535
90 #define FCGI_PADDING_SIZE 255
91 #define FCGI_RECORD_SIZE \
92 (sizeof(struct fcgi_record_header) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE)
94 #define FCGI_ALIGNMENT 8
95 #define FCGI_ALIGN(n) \
96 (((n) + (FCGI_ALIGNMENT - 1)) & ~(FCGI_ALIGNMENT - 1))
98 #define FD_RESERVE 5
99 #define FD_NEEDED 6
101 #define FCGI_BEGIN_REQUEST 1
102 #define FCGI_ABORT_REQUEST 2
103 #define FCGI_END_REQUEST 3
104 #define FCGI_PARAMS 4
105 #define FCGI_STDIN 5
106 #define FCGI_STDOUT 6
107 #define FCGI_STDERR 7
108 #define FCGI_DATA 8
109 #define FCGI_GET_VALUES 9
110 #define FCGI_GET_VALUES_RESULT 10
111 #define FCGI_UNKNOWN_TYPE 11
112 #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
114 #define FCGI_REQUEST_COMPLETE 0
115 #define FCGI_CANT_MPX_CONN 1
116 #define FCGI_OVERLOADED 2
117 #define FCGI_UNKNOWN_ROLE 3
119 #define GOTWEB_PACK_NUM_TEMPFILES (32 * 2)
121 /* Forward declaration */
122 struct got_blob_object;
123 struct got_tree_entry;
124 struct got_reflist_head;
126 enum imsg_type {
127 IMSG_CFG_SRV,
128 IMSG_CFG_SOCK,
129 IMSG_CFG_FD,
130 IMSG_CFG_DONE,
131 IMSG_CTL_START,
134 struct imsgev {
135 struct imsgbuf ibuf;
136 void (*handler)(int, short, void *);
137 struct event ev;
138 void *data;
139 short events;
142 #define IMSG_DATA_SIZE(imsg) ((imsg)->hdr.len - IMSG_HEADER_SIZE)
144 struct env_val {
145 SLIST_ENTRY(env_val) entry;
146 char *val;
148 SLIST_HEAD(env_head, env_val);
150 struct fcgi_record_header {
151 uint8_t version;
152 uint8_t type;
153 uint16_t id;
154 uint16_t content_len;
155 uint8_t padding_len;
156 uint8_t reserved;
157 }__attribute__((__packed__));
159 struct blame_line {
160 int annotated;
161 char *id_str;
162 char *committer;
163 char datebuf[11]; /* YYYY-MM-DD + NUL */
166 struct repo_dir {
167 char *name;
168 char *owner;
169 char *description;
170 char *url;
171 time_t age;
172 char *path;
175 struct repo_tag {
176 TAILQ_ENTRY(repo_tag) entry;
177 char *commit_id;
178 char *tag_name;
179 char *tag_commit;
180 char *commit_msg;
181 char *tagger;
182 time_t tagger_time;
185 struct repo_commit {
186 TAILQ_ENTRY(repo_commit) entry;
187 char *path;
188 char *refs_str;
189 char *commit_id; /* id_str1 */
190 char *parent_id; /* id_str2 */
191 char *tree_id;
192 char *author;
193 char *committer;
194 char *commit_msg;
195 time_t committer_time;
198 struct got_repository;
199 struct transport {
200 TAILQ_HEAD(repo_commits_head, repo_commit) repo_commits;
201 TAILQ_HEAD(repo_tags_head, repo_tag) repo_tags;
202 struct got_reflist_head refs;
203 struct got_repository *repo;
204 struct repo_dir *repo_dir;
205 struct querystring *qs;
206 char *more_id;
207 char *tags_more_id;
208 unsigned int repos_total;
209 unsigned int next_disp;
210 unsigned int prev_disp;
211 unsigned int tag_count;
212 const struct got_error *error;
213 struct got_blob_object *blob;
214 int fd;
215 FILE *fp;
216 struct dirent **repos;
217 int nrepos;
220 enum socket_priv_fds {
221 DIFF_FD_1,
222 DIFF_FD_2,
223 DIFF_FD_3,
224 DIFF_FD_4,
225 DIFF_FD_5,
226 BLAME_FD_1,
227 BLAME_FD_2,
228 BLAME_FD_3,
229 BLAME_FD_4,
230 BLAME_FD_5,
231 BLAME_FD_6,
232 BLOB_FD_1,
233 BLOB_FD_2,
234 PRIV_FDS__MAX,
237 struct template;
238 struct request {
239 struct socket *sock;
240 struct server *srv;
241 struct transport *t;
242 struct template *tp;
243 struct event ev;
244 struct event tmo;
246 uint16_t id;
247 int fd;
248 int priv_fd[PRIV_FDS__MAX];
250 uint8_t buf[FCGI_RECORD_SIZE];
251 size_t buf_pos;
252 size_t buf_len;
254 uint8_t outbuf[GOTWEBD_CACHESIZE];
256 char querystring[MAX_QUERYSTRING];
257 char document_uri[MAX_DOCUMENT_URI];
258 char server_name[MAX_SERVER_NAME];
259 int https;
261 uint8_t request_started;
264 struct fcgi_begin_request_body {
265 uint16_t role;
266 uint8_t flags;
267 uint8_t reserved[5];
268 }__attribute__((__packed__));
270 struct fcgi_end_request_body {
271 uint32_t app_status;
272 uint8_t protocol_status;
273 uint8_t reserved[3];
274 }__attribute__((__packed__));
276 struct address {
277 TAILQ_ENTRY(address) entry;
278 struct sockaddr_storage ss;
279 socklen_t slen;
280 int ai_family;
281 int ai_socktype;
282 int ai_protocol;
283 in_port_t port;
284 char ifname[IFNAMSIZ];
286 TAILQ_HEAD(addresslist, address);
288 struct server {
289 TAILQ_ENTRY(server) entry;
290 struct addresslist al;
292 char name[GOTWEBD_MAXTEXT];
294 char repos_path[PATH_MAX];
295 char site_name[GOTWEBD_MAXNAME];
296 char site_owner[GOTWEBD_MAXNAME];
297 char site_link[GOTWEBD_MAXTEXT];
298 char logo[GOTWEBD_MAXTEXT];
299 char logo_url[GOTWEBD_MAXTEXT];
300 char custom_css[PATH_MAX];
302 size_t max_repos_display;
303 size_t max_commits_display;
304 size_t summary_commits_display;
305 size_t summary_tags_display;
307 int show_site_owner;
308 int show_repo_owner;
309 int show_repo_age;
310 int show_repo_description;
311 int show_repo_cloneurl;
312 int respect_exportok;
314 int unix_socket;
315 char unix_socket_name[PATH_MAX];
317 int fcgi_socket;
319 TAILQ_HEAD(serverlist, server);
321 enum client_action {
322 CLIENT_CONNECT,
323 CLIENT_DISCONNECT,
326 struct socket_conf {
327 struct address addr;
329 char name[GOTWEBD_MAXTEXT];
330 char srv_name[GOTWEBD_MAXTEXT];
332 int id;
333 int af_type;
334 char unix_socket_name[PATH_MAX];
335 in_port_t fcgi_socket_port;
338 struct socket {
339 TAILQ_ENTRY(socket) entry;
340 struct socket_conf conf;
342 int fd;
343 int pack_fds[GOTWEB_PACK_NUM_TEMPFILES];
344 int priv_fd[PRIV_FDS__MAX];
346 struct event evt;
347 struct event ev;
348 struct event pause;
350 int client_status;
352 TAILQ_HEAD(socketlist, socket);
354 struct passwd;
355 struct gotwebd {
356 struct serverlist servers;
357 struct socketlist sockets;
359 const char *gotwebd_conffile;
361 int gotwebd_debug;
362 int gotwebd_verbose;
364 struct imsgev *iev_parent;
365 struct imsgev *iev_server;
366 size_t nserver;
368 struct passwd *pw;
370 uint16_t prefork_gotwebd;
371 int gotwebd_reload;
373 int server_cnt;
375 char httpd_chroot[PATH_MAX];
377 int unix_socket;
378 char unix_socket_name[PATH_MAX];
382 * URL parameter for gotweb_render_url. NULL values and int set to -1
383 * are implicitly ignored, and string are properly escaped.
385 struct gotweb_url {
386 int action;
387 int index_page;
388 const char *commit;
389 const char *previd;
390 const char *prevset;
391 const char *file;
392 const char *folder;
393 const char *headref;
394 const char *path;
397 struct querystring {
398 uint8_t action;
399 char *commit;
400 char *previd;
401 char *prevset;
402 char *file;
403 char *folder;
404 char *headref;
405 int index_page;
406 char *path;
409 struct querystring_keys {
410 const char *name;
411 int element;
414 struct action_keys {
415 const char *name;
416 int action;
419 enum querystring_elements {
420 ACTION,
421 COMMIT,
422 RFILE,
423 FOLDER,
424 HEADREF,
425 INDEX_PAGE,
426 PATH,
429 enum query_actions {
430 BLAME,
431 BLOB,
432 BLOBRAW,
433 BRIEFS,
434 COMMITS,
435 DIFF,
436 ERR,
437 INDEX,
438 PATCH,
439 SUMMARY,
440 TAG,
441 TAGS,
442 TREE,
443 RSS,
446 extern struct gotwebd *gotwebd_env;
448 typedef int (*got_render_blame_line_cb)(struct template *, const char *,
449 struct blame_line *, int, int);
451 /* gotwebd.c */
452 void imsg_event_add(struct imsgev *);
453 int imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
454 pid_t, int, const void *, uint16_t);
455 int main_compose_sockets(struct gotwebd *, uint32_t, int,
456 const void *, uint16_t);
457 int sockets_compose_main(struct gotwebd *, uint32_t,
458 const void *, uint16_t);
460 /* sockets.c */
461 void sockets(struct gotwebd *, int);
462 void sockets_parse_sockets(struct gotwebd *);
463 void sockets_socket_accept(int, short, void *);
464 int sockets_privinit(struct gotwebd *, struct socket *);
466 /* gotweb.c */
467 void gotweb_index_navs(struct request *, struct gotweb_url *, int *,
468 struct gotweb_url *, int *);
469 int gotweb_render_age(struct template *, time_t);
470 const struct got_error *gotweb_init_transport(struct transport **);
471 const char *gotweb_action_name(int);
472 int gotweb_render_url(struct request *, struct gotweb_url *);
473 int gotweb_render_absolute_url(struct request *, struct gotweb_url *);
474 void gotweb_free_repo_commit(struct repo_commit *);
475 void gotweb_free_repo_tag(struct repo_tag *);
476 void gotweb_process_request(struct request *);
477 void gotweb_free_transport(struct transport *);
479 /* pages.tmpl */
480 int gotweb_render_page(struct template *, int (*)(struct template *));
481 int gotweb_render_error(struct template *);
482 int gotweb_render_repo_table_hdr(struct template *);
483 int gotweb_render_repo_fragment(struct template *, struct repo_dir *);
484 int gotweb_render_briefs(struct template *);
485 int gotweb_render_navs(struct template *);
486 int gotweb_render_commits(struct template *);
487 int gotweb_render_blob(struct template *);
488 int gotweb_render_tree(struct template *);
489 int gotweb_render_tags(struct template *);
490 int gotweb_render_tag(struct template *);
491 int gotweb_render_diff(struct template *);
492 int gotweb_render_branches(struct template *, struct got_reflist_head *);
493 int gotweb_render_summary(struct template *);
494 int gotweb_render_blame(struct template *);
495 int gotweb_render_patch(struct template *);
496 int gotweb_render_rss(struct template *);
498 /* parse.y */
499 int parse_config(const char *, struct gotwebd *);
500 int cmdline_symset(char *);
502 /* fcgi.c */
503 void fcgi_request(int, short, void *);
504 void fcgi_timeout(int, short, void *);
505 void fcgi_cleanup_request(struct request *);
506 void fcgi_create_end_record(struct request *);
507 void dump_fcgi_record(const char *, struct fcgi_record_header *);
508 int fcgi_write(void *, const void *, size_t);
510 /* got_operations.c */
511 const struct got_error *got_gotweb_closefile(FILE *);
512 const struct got_error *got_get_repo_owner(char **, struct request *);
513 const struct got_error *got_get_repo_age(time_t *, struct request *,
514 const char *);
515 const struct got_error *got_get_repo_commits(struct request *, size_t);
516 const struct got_error *got_get_repo_tags(struct request *, size_t);
517 const struct got_error *got_get_repo_heads(struct request *);
518 const struct got_error *got_open_diff_for_output(FILE **, struct request *);
519 int got_output_repo_tree(struct request *, char **,
520 int (*)(struct template *, struct got_tree_entry *));
521 const struct got_error *got_open_blob_for_output(struct got_blob_object **,
522 int *, int *, struct request *, const char *, const char *, const char *);
523 int got_output_blob_by_lines(struct template *, struct got_blob_object *,
524 int (*)(struct template *, const char *, size_t));
525 const struct got_error *got_output_file_blame(struct request *,
526 got_render_blame_line_cb);
528 /* config.c */
529 int config_setserver(struct gotwebd *, struct server *);
530 int config_getserver(struct gotwebd *, struct imsg *);
531 int config_setsock(struct gotwebd *, struct socket *);
532 int config_getsock(struct gotwebd *, struct imsg *);
533 int config_setfd(struct gotwebd *, struct socket *);
534 int config_getfd(struct gotwebd *, struct imsg *);
535 int config_getcfg(struct gotwebd *, struct imsg *);
536 int config_init(struct gotwebd *);
538 /* log.c */
539 void log_init(int, int);
540 void log_procinit(const char *);
541 void log_setverbose(int);
542 int log_getverbose(void);
543 void log_warn(const char *, ...)
544 __attribute__((__format__ (printf, 1, 2)));
545 void log_warnx(const char *, ...)
546 __attribute__((__format__ (printf, 1, 2)));
547 void log_info(const char *, ...)
548 __attribute__((__format__ (printf, 1, 2)));
549 void log_debug(const char *, ...)
550 __attribute__((__format__ (printf, 1, 2)));
551 void logit(int, const char *, ...)
552 __attribute__((__format__ (printf, 2, 3)));
553 void vlog(int, const char *, va_list)
554 __attribute__((__format__ (printf, 2, 0)));
555 __dead void fatal(const char *, ...)
556 __attribute__((__format__ (printf, 1, 2)));
557 __dead void fatalx(const char *, ...)
558 __attribute__((__format__ (printf, 1, 2)));