delete trailing whitespaces
[got-portable.git] / gotwebd / gotwebd.h
blob59fef09083a448dfb1173969b2c5b5426af439a8
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 #ifndef nitems
28 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
29 #endif
31 /* GOTWEBD DEFAULTS */
32 #define GOTWEBD_CONF "/etc/gotwebd.conf"
34 #ifndef GOTWEBD_DEFAULT_USER
35 #define GOTWEBD_DEFAULT_USER "www"
36 #endif
38 #define GOTWEBD_MAXDESCRSZ 1024
39 #define GOTWEBD_MAXCLONEURLSZ 1024
40 #define GOTWEBD_CACHESIZE 1024
41 #define GOTWEBD_MAXCLIENTS 1024
42 #define GOTWEBD_MAXTEXT 511
43 #define GOTWEBD_MAXNAME 64
44 #define GOTWEBD_MAXPORT 6
45 #define GOTWEBD_NUMPROC 3
46 #define GOTWEBD_SOCK_FILENO 3
48 #define PROC_MAX_INSTANCES 32
50 /* GOTWEB DEFAULTS */
51 #define MAX_QUERYSTRING 2048
52 #define MAX_DOCUMENT_URI 255
53 #define MAX_SERVER_NAME 255
55 #define GOTWEB_GIT_DIR ".git"
57 #define D_HTTPD_CHROOT "/var/www"
58 #define D_UNIX_SOCKET "/run/gotweb.sock"
59 #define D_FCGI_PORT "9000"
60 #define D_GOTPATH "/got/public"
61 #define D_SITENAME "Gotweb"
62 #define D_SITEOWNER "Got Owner"
63 #define D_SITELINK "Repos"
64 #define D_GOTLOGO "got.png"
65 #define D_GOTURL "https://gameoftrees.org"
66 #define D_GOTWEBCSS "gotweb.css"
68 #define D_SHOWROWNER 1
69 #define D_SHOWSOWNER 1
70 #define D_SHOWAGE 1
71 #define D_SHOWDESC 1
72 #define D_SHOWURL 1
73 #define D_RESPECTEXPORTOK 0
74 #define D_MAXREPODISP 25
75 #define D_MAXSLCOMMDISP 10
76 #define D_MAXCOMMITDISP 25
77 #define D_MAXSLTAGDISP 3
79 #define BUF 8192
81 #define TIMEOUT_DEFAULT 120
83 #define FCGI_CONTENT_SIZE 65535
84 #define FCGI_PADDING_SIZE 255
85 #define FCGI_RECORD_SIZE \
86 (sizeof(struct fcgi_record_header) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE)
88 #define FCGI_ALIGNMENT 8
89 #define FCGI_ALIGN(n) \
90 (((n) + (FCGI_ALIGNMENT - 1)) & ~(FCGI_ALIGNMENT - 1))
92 #define FD_RESERVE 5
93 #define FD_NEEDED 6
95 #define FCGI_BEGIN_REQUEST 1
96 #define FCGI_ABORT_REQUEST 2
97 #define FCGI_END_REQUEST 3
98 #define FCGI_PARAMS 4
99 #define FCGI_STDIN 5
100 #define FCGI_STDOUT 6
101 #define FCGI_STDERR 7
102 #define FCGI_DATA 8
103 #define FCGI_GET_VALUES 9
104 #define FCGI_GET_VALUES_RESULT 10
105 #define FCGI_UNKNOWN_TYPE 11
106 #define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)
108 #define FCGI_REQUEST_COMPLETE 0
109 #define FCGI_CANT_MPX_CONN 1
110 #define FCGI_OVERLOADED 2
111 #define FCGI_UNKNOWN_ROLE 3
113 #define GOTWEB_PACK_NUM_TEMPFILES (32 * 2)
115 /* Forward declaration */
116 struct got_blob_object;
117 struct got_tree_entry;
118 struct got_reflist_head;
120 enum imsg_type {
121 IMSG_CFG_SRV,
122 IMSG_CFG_SOCK,
123 IMSG_CFG_FD,
124 IMSG_CFG_DONE,
125 IMSG_CTL_START,
128 struct imsgev {
129 struct imsgbuf ibuf;
130 void (*handler)(int, short, void *);
131 struct event ev;
132 void *data;
133 short events;
136 #define IMSG_DATA_SIZE(imsg) ((imsg)->hdr.len - IMSG_HEADER_SIZE)
138 struct env_val {
139 SLIST_ENTRY(env_val) entry;
140 char *val;
142 SLIST_HEAD(env_head, env_val);
144 struct fcgi_record_header {
145 uint8_t version;
146 uint8_t type;
147 uint16_t id;
148 uint16_t content_len;
149 uint8_t padding_len;
150 uint8_t reserved;
151 }__attribute__((__packed__));
153 struct blame_line {
154 int annotated;
155 char *id_str;
156 char *committer;
157 char datebuf[11]; /* YYYY-MM-DD + NUL */
160 struct repo_dir {
161 char *name;
162 char *owner;
163 char *description;
164 char *url;
165 time_t age;
166 char *path;
169 struct repo_tag {
170 TAILQ_ENTRY(repo_tag) entry;
171 char *commit_id;
172 char *tag_name;
173 char *tag_commit;
174 char *commit_msg;
175 char *tagger;
176 time_t tagger_time;
179 struct repo_commit {
180 TAILQ_ENTRY(repo_commit) entry;
181 char *path;
182 char *refs_str;
183 char *commit_id; /* id_str1 */
184 char *parent_id; /* id_str2 */
185 char *tree_id;
186 char *author;
187 char *committer;
188 char *commit_msg;
189 time_t committer_time;
192 struct got_repository;
193 struct transport {
194 TAILQ_HEAD(repo_commits_head, repo_commit) repo_commits;
195 TAILQ_HEAD(repo_tags_head, repo_tag) repo_tags;
196 struct got_reflist_head refs;
197 struct got_repository *repo;
198 struct repo_dir *repo_dir;
199 struct querystring *qs;
200 char *more_id;
201 char *tags_more_id;
202 unsigned int repos_total;
203 unsigned int next_disp;
204 unsigned int prev_disp;
205 const struct got_error *error;
206 struct got_blob_object *blob;
207 int fd;
208 FILE *fp;
209 struct dirent **repos;
210 int nrepos;
213 enum socket_priv_fds {
214 DIFF_FD_1,
215 DIFF_FD_2,
216 DIFF_FD_3,
217 DIFF_FD_4,
218 DIFF_FD_5,
219 BLAME_FD_1,
220 BLAME_FD_2,
221 BLAME_FD_3,
222 BLAME_FD_4,
223 BLAME_FD_5,
224 BLAME_FD_6,
225 BLOB_FD_1,
226 BLOB_FD_2,
227 PRIV_FDS__MAX,
230 struct template;
231 struct request {
232 struct socket *sock;
233 struct server *srv;
234 struct transport *t;
235 struct template *tp;
236 struct event ev;
237 struct event tmo;
239 uint16_t id;
240 int fd;
241 int priv_fd[PRIV_FDS__MAX];
243 uint8_t buf[FCGI_RECORD_SIZE];
244 size_t buf_pos;
245 size_t buf_len;
247 uint8_t outbuf[GOTWEBD_CACHESIZE];
249 char querystring[MAX_QUERYSTRING];
250 char document_uri[MAX_DOCUMENT_URI];
251 char server_name[MAX_SERVER_NAME];
252 int https;
254 uint8_t request_started;
257 struct fcgi_begin_request_body {
258 uint16_t role;
259 uint8_t flags;
260 uint8_t reserved[5];
261 }__attribute__((__packed__));
263 struct fcgi_end_request_body {
264 uint32_t app_status;
265 uint8_t protocol_status;
266 uint8_t reserved[3];
267 }__attribute__((__packed__));
269 struct address {
270 TAILQ_ENTRY(address) entry;
271 struct sockaddr_storage ss;
272 socklen_t slen;
273 int ai_family;
274 int ai_socktype;
275 int ai_protocol;
276 in_port_t port;
277 char ifname[IFNAMSIZ];
279 TAILQ_HEAD(addresslist, address);
281 struct server {
282 TAILQ_ENTRY(server) entry;
284 char name[GOTWEBD_MAXTEXT];
286 char repos_path[PATH_MAX];
287 char site_name[GOTWEBD_MAXNAME];
288 char site_owner[GOTWEBD_MAXNAME];
289 char site_link[GOTWEBD_MAXTEXT];
290 char logo[GOTWEBD_MAXTEXT];
291 char logo_url[GOTWEBD_MAXTEXT];
292 char custom_css[PATH_MAX];
294 size_t max_repos_display;
295 size_t max_commits_display;
296 size_t summary_commits_display;
297 size_t summary_tags_display;
299 int show_site_owner;
300 int show_repo_owner;
301 int show_repo_age;
302 int show_repo_description;
303 int show_repo_cloneurl;
304 int respect_exportok;
306 TAILQ_HEAD(serverlist, server);
308 enum client_action {
309 CLIENT_CONNECT,
310 CLIENT_DISCONNECT,
313 struct socket_conf {
314 struct address addr;
316 int id;
317 int af_type;
318 char unix_socket_name[PATH_MAX];
319 in_port_t fcgi_socket_port;
322 struct socket {
323 TAILQ_ENTRY(socket) entry;
324 struct socket_conf conf;
326 int fd;
327 struct event evt;
328 struct event ev;
329 struct event pause;
331 int client_status;
333 TAILQ_HEAD(socketlist, socket);
335 struct passwd;
336 struct gotwebd {
337 struct serverlist servers;
338 struct socketlist sockets;
339 struct addresslist addresses;
341 int pack_fds[GOTWEB_PACK_NUM_TEMPFILES];
342 int priv_fd[PRIV_FDS__MAX];
344 char *user;
345 const char *gotwebd_conffile;
347 int gotwebd_debug;
348 int gotwebd_verbose;
350 struct imsgev *iev_parent;
351 struct imsgev *iev_server;
352 size_t nserver;
354 struct passwd *pw;
356 uint16_t prefork_gotwebd;
357 int gotwebd_reload;
359 int server_cnt;
361 char httpd_chroot[PATH_MAX];
365 * URL parameter for gotweb_render_url. NULL values and int set to -1
366 * are implicitly ignored, and string are properly escaped.
368 struct gotweb_url {
369 int action;
370 int index_page;
371 const char *commit;
372 const char *file;
373 const char *folder;
374 const char *headref;
375 const char *path;
378 struct querystring {
379 uint8_t action;
380 char *commit;
381 char *file;
382 char *folder;
383 char *headref;
384 int index_page;
385 char *path;
388 struct querystring_keys {
389 const char *name;
390 int element;
393 struct action_keys {
394 const char *name;
395 int action;
398 enum querystring_elements {
399 ACTION,
400 COMMIT,
401 RFILE,
402 FOLDER,
403 HEADREF,
404 INDEX_PAGE,
405 PATH,
408 enum query_actions {
409 BLAME,
410 BLOB,
411 BLOBRAW,
412 BRIEFS,
413 COMMITS,
414 DIFF,
415 ERR,
416 INDEX,
417 PATCH,
418 SUMMARY,
419 TAG,
420 TAGS,
421 TREE,
422 RSS,
425 extern struct gotwebd *gotwebd_env;
427 typedef int (*got_render_blame_line_cb)(struct template *, const char *,
428 struct blame_line *, int, int);
430 /* gotwebd.c */
431 void imsg_event_add(struct imsgev *);
432 int imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
433 pid_t, int, const void *, uint16_t);
434 int main_compose_sockets(struct gotwebd *, uint32_t, int,
435 const void *, uint16_t);
436 int sockets_compose_main(struct gotwebd *, uint32_t,
437 const void *, uint16_t);
439 /* sockets.c */
440 void sockets(struct gotwebd *, int);
441 void sockets_parse_sockets(struct gotwebd *);
442 void sockets_socket_accept(int, short, void *);
443 int sockets_privinit(struct gotwebd *, struct socket *);
445 /* gotweb.c */
446 void gotweb_index_navs(struct request *, struct gotweb_url *, int *,
447 struct gotweb_url *, int *);
448 int gotweb_render_age(struct template *, time_t);
449 const struct got_error *gotweb_init_transport(struct transport **);
450 const char *gotweb_action_name(int);
451 int gotweb_render_url(struct request *, struct gotweb_url *);
452 int gotweb_render_absolute_url(struct request *, struct gotweb_url *);
453 void gotweb_free_repo_commit(struct repo_commit *);
454 void gotweb_free_repo_tag(struct repo_tag *);
455 void gotweb_process_request(struct request *);
456 void gotweb_free_transport(struct transport *);
458 /* pages.tmpl */
459 int gotweb_render_page(struct template *, int (*)(struct template *));
460 int gotweb_render_error(struct template *);
461 int gotweb_render_repo_table_hdr(struct template *);
462 int gotweb_render_repo_fragment(struct template *, struct repo_dir *);
463 int gotweb_render_briefs(struct template *);
464 int gotweb_render_navs(struct template *);
465 int gotweb_render_commits(struct template *);
466 int gotweb_render_blob(struct template *);
467 int gotweb_render_tree(struct template *);
468 int gotweb_render_tags(struct template *);
469 int gotweb_render_tag(struct template *);
470 int gotweb_render_diff(struct template *);
471 int gotweb_render_branches(struct template *, struct got_reflist_head *);
472 int gotweb_render_summary(struct template *);
473 int gotweb_render_blame(struct template *);
474 int gotweb_render_patch(struct template *);
475 int gotweb_render_rss(struct template *);
477 /* parse.y */
478 int parse_config(const char *, struct gotwebd *);
479 int cmdline_symset(char *);
481 /* fcgi.c */
482 void fcgi_request(int, short, void *);
483 void fcgi_timeout(int, short, void *);
484 void fcgi_cleanup_request(struct request *);
485 void fcgi_create_end_record(struct request *);
486 void dump_fcgi_record(const char *, struct fcgi_record_header *);
487 int fcgi_write(void *, const void *, size_t);
489 /* got_operations.c */
490 const struct got_error *got_gotweb_closefile(FILE *);
491 const struct got_error *got_get_repo_owner(char **, struct request *);
492 const struct got_error *got_get_repo_age(time_t *, struct request *,
493 const char *);
494 const struct got_error *got_get_repo_commits(struct request *, size_t);
495 const struct got_error *got_get_repo_tags(struct request *, size_t);
496 const struct got_error *got_get_repo_heads(struct request *);
497 const struct got_error *got_open_diff_for_output(FILE **, struct request *);
498 int got_output_repo_tree(struct request *, char **,
499 int (*)(struct template *, struct got_tree_entry *));
500 const struct got_error *got_open_blob_for_output(struct got_blob_object **,
501 int *, int *, struct request *, const char *, const char *, const char *);
502 int got_output_blob_by_lines(struct template *, struct got_blob_object *,
503 int (*)(struct template *, const char *, size_t));
504 const struct got_error *got_output_file_blame(struct request *,
505 got_render_blame_line_cb);
507 /* config.c */
508 int config_setserver(struct gotwebd *, struct server *);
509 int config_getserver(struct gotwebd *, struct imsg *);
510 int config_setsock(struct gotwebd *, struct socket *);
511 int config_getsock(struct gotwebd *, struct imsg *);
512 int config_setfd(struct gotwebd *);
513 int config_getfd(struct gotwebd *, struct imsg *);
514 int config_getcfg(struct gotwebd *, struct imsg *);
515 int config_init(struct gotwebd *);