gotwebd: allow to change the user
[got-portable.git] / gotwebd / gotwebd.h
blob54d00805fd26e7a6b11e21510aad032bf7d9e1bc
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 unsigned int tag_count;
206 const struct got_error *error;
207 struct got_blob_object *blob;
208 int fd;
209 FILE *fp;
210 struct dirent **repos;
211 int nrepos;
214 enum socket_priv_fds {
215 DIFF_FD_1,
216 DIFF_FD_2,
217 DIFF_FD_3,
218 DIFF_FD_4,
219 DIFF_FD_5,
220 BLAME_FD_1,
221 BLAME_FD_2,
222 BLAME_FD_3,
223 BLAME_FD_4,
224 BLAME_FD_5,
225 BLAME_FD_6,
226 BLOB_FD_1,
227 BLOB_FD_2,
228 PRIV_FDS__MAX,
231 struct template;
232 struct request {
233 struct socket *sock;
234 struct server *srv;
235 struct transport *t;
236 struct template *tp;
237 struct event ev;
238 struct event tmo;
240 uint16_t id;
241 int fd;
242 int priv_fd[PRIV_FDS__MAX];
244 uint8_t buf[FCGI_RECORD_SIZE];
245 size_t buf_pos;
246 size_t buf_len;
248 uint8_t outbuf[GOTWEBD_CACHESIZE];
250 char querystring[MAX_QUERYSTRING];
251 char document_uri[MAX_DOCUMENT_URI];
252 char server_name[MAX_SERVER_NAME];
253 int https;
255 uint8_t request_started;
258 struct fcgi_begin_request_body {
259 uint16_t role;
260 uint8_t flags;
261 uint8_t reserved[5];
262 }__attribute__((__packed__));
264 struct fcgi_end_request_body {
265 uint32_t app_status;
266 uint8_t protocol_status;
267 uint8_t reserved[3];
268 }__attribute__((__packed__));
270 struct address {
271 TAILQ_ENTRY(address) entry;
272 struct sockaddr_storage ss;
273 socklen_t slen;
274 int ai_family;
275 int ai_socktype;
276 int ai_protocol;
277 in_port_t port;
278 char ifname[IFNAMSIZ];
280 TAILQ_HEAD(addresslist, address);
282 struct server {
283 TAILQ_ENTRY(server) entry;
285 char name[GOTWEBD_MAXTEXT];
287 char repos_path[PATH_MAX];
288 char site_name[GOTWEBD_MAXNAME];
289 char site_owner[GOTWEBD_MAXNAME];
290 char site_link[GOTWEBD_MAXTEXT];
291 char logo[GOTWEBD_MAXTEXT];
292 char logo_url[GOTWEBD_MAXTEXT];
293 char custom_css[PATH_MAX];
295 size_t max_repos_display;
296 size_t max_commits_display;
297 size_t summary_commits_display;
298 size_t summary_tags_display;
300 int show_site_owner;
301 int show_repo_owner;
302 int show_repo_age;
303 int show_repo_description;
304 int show_repo_cloneurl;
305 int respect_exportok;
307 TAILQ_HEAD(serverlist, server);
309 enum client_action {
310 CLIENT_CONNECT,
311 CLIENT_DISCONNECT,
314 struct socket_conf {
315 struct address addr;
317 int id;
318 int af_type;
319 char unix_socket_name[PATH_MAX];
320 in_port_t fcgi_socket_port;
323 struct socket {
324 TAILQ_ENTRY(socket) entry;
325 struct socket_conf conf;
327 int fd;
328 int pack_fds[GOTWEB_PACK_NUM_TEMPFILES];
329 int priv_fd[PRIV_FDS__MAX];
331 struct event evt;
332 struct event ev;
333 struct event pause;
335 int client_status;
337 TAILQ_HEAD(socketlist, socket);
339 struct passwd;
340 struct gotwebd {
341 struct serverlist servers;
342 struct socketlist sockets;
343 struct addresslist addresses;
345 char *user;
346 const char *gotwebd_conffile;
348 int gotwebd_debug;
349 int gotwebd_verbose;
351 struct imsgev *iev_parent;
352 struct imsgev *iev_server;
353 size_t nserver;
355 struct passwd *pw;
357 uint16_t prefork_gotwebd;
358 int gotwebd_reload;
360 int server_cnt;
362 char httpd_chroot[PATH_MAX];
366 * URL parameter for gotweb_render_url. NULL values and int set to -1
367 * are implicitly ignored, and string are properly escaped.
369 struct gotweb_url {
370 int action;
371 int index_page;
372 const char *commit;
373 const char *previd;
374 const char *prevset;
375 const char *file;
376 const char *folder;
377 const char *headref;
378 const char *path;
381 struct querystring {
382 uint8_t action;
383 char *commit;
384 char *previd;
385 char *prevset;
386 char *file;
387 char *folder;
388 char *headref;
389 int index_page;
390 char *path;
393 struct querystring_keys {
394 const char *name;
395 int element;
398 struct action_keys {
399 const char *name;
400 int action;
403 enum querystring_elements {
404 ACTION,
405 COMMIT,
406 RFILE,
407 FOLDER,
408 HEADREF,
409 INDEX_PAGE,
410 PATH,
413 enum query_actions {
414 BLAME,
415 BLOB,
416 BLOBRAW,
417 BRIEFS,
418 COMMITS,
419 DIFF,
420 ERR,
421 INDEX,
422 PATCH,
423 SUMMARY,
424 TAG,
425 TAGS,
426 TREE,
427 RSS,
430 extern struct gotwebd *gotwebd_env;
432 typedef int (*got_render_blame_line_cb)(struct template *, const char *,
433 struct blame_line *, int, int);
435 /* gotwebd.c */
436 void imsg_event_add(struct imsgev *);
437 int imsg_compose_event(struct imsgev *, uint16_t, uint32_t,
438 pid_t, int, const void *, uint16_t);
439 int main_compose_sockets(struct gotwebd *, uint32_t, int,
440 const void *, uint16_t);
441 int sockets_compose_main(struct gotwebd *, uint32_t,
442 const void *, uint16_t);
444 /* sockets.c */
445 void sockets(struct gotwebd *, int);
446 void sockets_parse_sockets(struct gotwebd *);
447 void sockets_socket_accept(int, short, void *);
448 int sockets_privinit(struct gotwebd *, struct socket *);
450 /* gotweb.c */
451 void gotweb_index_navs(struct request *, struct gotweb_url *, int *,
452 struct gotweb_url *, int *);
453 int gotweb_render_age(struct template *, time_t);
454 const struct got_error *gotweb_init_transport(struct transport **);
455 const char *gotweb_action_name(int);
456 int gotweb_render_url(struct request *, struct gotweb_url *);
457 int gotweb_render_absolute_url(struct request *, struct gotweb_url *);
458 void gotweb_free_repo_commit(struct repo_commit *);
459 void gotweb_free_repo_tag(struct repo_tag *);
460 void gotweb_process_request(struct request *);
461 void gotweb_free_transport(struct transport *);
463 /* pages.tmpl */
464 int gotweb_render_page(struct template *, int (*)(struct template *));
465 int gotweb_render_error(struct template *);
466 int gotweb_render_repo_table_hdr(struct template *);
467 int gotweb_render_repo_fragment(struct template *, struct repo_dir *);
468 int gotweb_render_briefs(struct template *);
469 int gotweb_render_navs(struct template *);
470 int gotweb_render_commits(struct template *);
471 int gotweb_render_blob(struct template *);
472 int gotweb_render_tree(struct template *);
473 int gotweb_render_tags(struct template *);
474 int gotweb_render_tag(struct template *);
475 int gotweb_render_diff(struct template *);
476 int gotweb_render_branches(struct template *, struct got_reflist_head *);
477 int gotweb_render_summary(struct template *);
478 int gotweb_render_blame(struct template *);
479 int gotweb_render_patch(struct template *);
480 int gotweb_render_rss(struct template *);
482 /* parse.y */
483 int parse_config(const char *, struct gotwebd *);
484 int cmdline_symset(char *);
486 /* fcgi.c */
487 void fcgi_request(int, short, void *);
488 void fcgi_timeout(int, short, void *);
489 void fcgi_cleanup_request(struct request *);
490 void fcgi_create_end_record(struct request *);
491 void dump_fcgi_record(const char *, struct fcgi_record_header *);
492 int fcgi_write(void *, const void *, size_t);
494 /* got_operations.c */
495 const struct got_error *got_gotweb_closefile(FILE *);
496 const struct got_error *got_get_repo_owner(char **, struct request *);
497 const struct got_error *got_get_repo_age(time_t *, struct request *,
498 const char *);
499 const struct got_error *got_get_repo_commits(struct request *, size_t);
500 const struct got_error *got_get_repo_tags(struct request *, size_t);
501 const struct got_error *got_get_repo_heads(struct request *);
502 const struct got_error *got_open_diff_for_output(FILE **, struct request *);
503 int got_output_repo_tree(struct request *, char **,
504 int (*)(struct template *, struct got_tree_entry *));
505 const struct got_error *got_open_blob_for_output(struct got_blob_object **,
506 int *, int *, struct request *, const char *, const char *, const char *);
507 int got_output_blob_by_lines(struct template *, struct got_blob_object *,
508 int (*)(struct template *, const char *, size_t));
509 const struct got_error *got_output_file_blame(struct request *,
510 got_render_blame_line_cb);
512 /* config.c */
513 int config_setserver(struct gotwebd *, struct server *);
514 int config_getserver(struct gotwebd *, struct imsg *);
515 int config_setsock(struct gotwebd *, struct socket *);
516 int config_getsock(struct gotwebd *, struct imsg *);
517 int config_setfd(struct gotwebd *, struct socket *);
518 int config_getfd(struct gotwebd *, struct imsg *);
519 int config_getcfg(struct gotwebd *, struct imsg *);
520 int config_init(struct gotwebd *);