Blob
- Date:
- Message:
- import gotwebd thread fcgi response to client for rendering in browser as data is returned fix potential problem with a stuck loop if the client is hammering the server with random clicks and stop/restarts render our index! WOOHOO! small var refactoring. fcgi.c to handle all clean-up, various error clean-up remove output used to trace down got bug temporarily stop overloading a socket, but a better solution needs to be found return on fcgi_gen_response, so we can track if a client is writable or not this stops page creation when the client is unavailable remove old comments enable profile building, although, i don't think this works thoroughly in a priv/proc daemon catch more errors correctly count repos remove temp logger we don't need to start our responder thread so early. move it to fcgi.c and start when we start processing html kill the unneeded thread, stop queueing responses, and just write to clients immediately clean up some memory leaks and dead stores rework querystring so an error can be displayed instead of showing the index on querystring error get framework in place for the rest of the content add server struct to response struct bo last commit get back a usable gotweb. not sure what i was thinking yesterday properly move our structs around this time remember index page for sitelink, fix leak unused var is annoying, so stop it for now. don't forget to change this! style briefs nearly completed. finish briefs output add briefs to summary cleanup some html properly retrieve next and previous commit ids for list navigation follow naddy's stailq macro change we will never have a previous link on the summary page goto correct label, so we get a previous link on the last page of briefs don't wrap short line simplify got_get_repo_commits code start rendering a diff start rendering a diff this was by accident finish diff output functions cleanup prepare for fd request that was a stupid idea, just flush the priv_fd bo that too. that won't work eith with append in mkstemp that isn't going to work actually zero out the priv_fd missed seek to beginning of file was overwriting first line of diff fsync our fd as well add link to repo path by sitelink and add back verbose fcgi debugging that was removed add modest write heuristics to fcgi_send_response fix dead assignments and XXX comment where a leak is happening that I can't find right now there was no leak. stsp is brilliant and knew it was the cache growing prevent double-free, render prettier err output if we can remove unused variables correctly fix double-free fix gotwebd to build with main's changes after rebase fix double-free don't error on index if pack files missing and fixup some error handling render commits finish up tag briefs and start the tag page finish up tag page unbreak TAGS and SUMMARY actions grab the correct tag from the queue unbreak TAGS and SUMMARY actions again update some error handling clean up unneeded code and start tree output render tree render branches remove tags from summary if there aren't any fix tree div structure and start blob render render blob render blame fix tree href in briefs clean up some css add headref to querystrings load correct commit for tree and diff fixup some error output update some copyright dates add full SNI support rm debug line found by Lucas6023, notified via IRC. thanks!! fix tree fix crash when querystring is manipulated to not have a commit id in certain instances. also break a stuck while loop on client error. fix for new got_object_id_by_path arguments rebase and fix prep for multiple fds per socket, instead of just one fix overlooked shift/reduce conflicts backout priv_fds as a list. after discussion with stsp, an array and length are the better direction prepare array of fds to pass into got functions make a new set of pack fds, which will be passed to got_repo_open work with new pack_fds in got_repo_open give output when no tags exist escape html in blame output change files listed in tree view to show blob, file commits, and blame, instead of blob, blob, blame. idea from mp4 on irc. this is way more handy. stop populating the queue from the headref and figure out previous commit id while iterating. this should reduce some overhead. actually purge our sockets instead of not using the function start work with new blob rm volatile use new diff change func names no more temp files increase blame number line width set content-type to text/plain so firefox won't download files rm test infra for now account for -Wwrite-strings fix for sigs and algorithm choice clean up some leaks and other mistakes
- Actions:
- History | Blame | Raw File
1 /*2 * Copyright (c) 2016, 2019, 2020-2021 Tracey Emery <tracey@traceyemery.net>3 * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>4 *5 * Permission to use, copy, modify, and distribute this software for any6 * purpose with or without fee is hereby granted, provided that the above7 * copyright notice and this permission notice appear in all copies.8 *9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.16 */18 #include <sys/param.h>19 #include <sys/queue.h>20 #include <sys/socket.h>21 #include <sys/wait.h>22 #include <sys/cdefs.h>24 #include <net/if.h>25 #include <netinet/in.h>27 #include <stdio.h>28 #include <stdlib.h>29 #include <string.h>30 #include <termios.h>31 #include <err.h>32 #include <errno.h>33 #include <event.h>34 #include <fcntl.h>35 #include <imsg.h>36 #include <pwd.h>37 #include <signal.h>38 #include <syslog.h>39 #include <unistd.h>40 #include <ctype.h>41 #include <util.h>43 #include "got_opentemp.h"45 #include "proc.h"46 #include "gotwebd.h"48 __dead void usage(void);50 int main(int, char **);51 int gotwebd_configure(struct gotwebd *);52 void gotwebd_configure_done(struct gotwebd *);53 void gotwebd_sighdlr(int sig, short event, void *arg);54 void gotwebd_shutdown(void);55 int gotwebd_dispatch_sockets(int, struct privsep_proc *, struct imsg *);57 struct gotwebd *gotwebd_env;59 static struct privsep_proc procs[] = {60 { "sockets", PROC_SOCKS, gotwebd_dispatch_sockets, sockets,61 sockets_shutdown },62 };64 int65 gotwebd_dispatch_sockets(int fd, struct privsep_proc *p, struct imsg *imsg)66 {67 struct privsep *ps = p->p_ps;68 struct gotwebd *env = ps->ps_env;70 switch (imsg->hdr.type) {71 case IMSG_CFG_DONE:72 gotwebd_configure_done(env);73 break;74 default:75 return (-1);76 }78 return (0);79 }81 void82 gotwebd_sighdlr(int sig, short event, void *arg)83 {84 /* struct privsep *ps = arg; */86 if (privsep_process != PROC_GOTWEBD)87 return;89 switch (sig) {90 case SIGHUP:91 log_info("%s: ignoring SIGHUP", __func__);92 break;93 case SIGPIPE:94 log_info("%s: ignoring SIGPIPE", __func__);95 break;96 case SIGUSR1:97 log_info("%s: ignoring SIGUSR1", __func__);98 break;99 case SIGTERM:100 case SIGINT:101 gotwebd_shutdown();102 break;103 default:104 fatalx("unexpected signal");105 }106 }108 __dead void109 usage(void)110 {111 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",112 getprogname());113 exit(1);114 }116 int117 main(int argc, char **argv)118 {119 struct gotwebd *env;120 struct privsep *ps;121 unsigned int proc;122 int ch;123 const char *conffile = GOTWEBD_CONF;124 enum privsep_procid proc_id = PROC_GOTWEBD;125 int proc_instance = 0;126 const char *errp, *title = NULL;127 int argc0 = argc;129 env = calloc(1, sizeof(*env));130 if (env == NULL)131 fatal("%s: calloc", __func__);133 /* XXX: add s and S for both sockets */134 while ((ch = getopt(argc, argv, "D:P:I:df:vn")) != -1) {135 switch (ch) {136 case 'D':137 if (cmdline_symset(optarg) < 0)138 log_warnx("could not parse macro definition %s",139 optarg);140 break;141 case 'd':142 env->gotwebd_debug = 2;143 break;144 case 'f':145 conffile = optarg;146 break;147 case 'v':148 env->gotwebd_verbose++;149 break;150 case 'n':151 env->gotwebd_debug = 2;152 env->gotwebd_noaction = 1;153 break;154 case 'P':155 title = optarg;156 proc_id = proc_getid(procs, nitems(procs), title);157 if (proc_id == PROC_MAX)158 fatalx("invalid process name");159 break;160 case 'I':161 proc_instance = strtonum(optarg, 0,162 PROC_MAX_INSTANCES, &errp);163 if (errp)164 fatalx("invalid process instance");165 break;166 default:167 usage();168 }169 }171 /* log to stderr until daemonized */172 log_init(env->gotwebd_debug ? env->gotwebd_debug : 1, LOG_DAEMON);174 argc -= optind;175 if (argc > 0)176 usage();178 ps = calloc(1, sizeof(*ps));179 if (ps == NULL)180 fatal("%s: calloc:", __func__);182 gotwebd_env = env;183 env->gotwebd_ps = ps;184 ps->ps_env = env;185 env->gotwebd_conffile = conffile;187 if (parse_config(env->gotwebd_conffile, env) == -1)188 exit(1);190 if (env->gotwebd_noaction && !env->gotwebd_debug)191 env->gotwebd_debug = 1;193 /* check for root privileges */194 if (env->gotwebd_noaction == 0) {195 if (geteuid())196 fatalx("need root privileges");197 }199 ps->ps_pw = getpwnam(GOTWEBD_USER);200 if (ps->ps_pw == NULL)201 fatalx("unknown user %s", GOTWEBD_USER);203 log_init(env->gotwebd_debug, LOG_DAEMON);204 log_setverbose(env->gotwebd_verbose);206 if (env->gotwebd_noaction)207 ps->ps_noaction = 1;209 ps->ps_instances[PROC_SOCKS] = env->prefork_gotwebd;210 ps->ps_instance = proc_instance;211 if (title != NULL)212 ps->ps_title[proc_id] = title;214 for (proc = 0; proc < nitems(procs); proc++)215 procs[proc].p_chroot = strlen(env->httpd_chroot) ?216 env->httpd_chroot : D_HTTPD_CHROOT;218 /* only the gotwebd returns */219 proc_init(ps, procs, nitems(procs), argc0, argv, proc_id);221 log_procinit("gotwebd");222 if (!env->gotwebd_debug && daemon(0, 0) == -1)223 fatal("can't daemonize");225 if (ps->ps_noaction == 0)226 log_info("%s startup", getprogname());228 event_init();230 signal_set(&ps->ps_evsigint, SIGINT, gotwebd_sighdlr, ps);231 signal_set(&ps->ps_evsigterm, SIGTERM, gotwebd_sighdlr, ps);232 signal_set(&ps->ps_evsighup, SIGHUP, gotwebd_sighdlr, ps);233 signal_set(&ps->ps_evsigpipe, SIGPIPE, gotwebd_sighdlr, ps);234 signal_set(&ps->ps_evsigusr1, SIGUSR1, gotwebd_sighdlr, ps);236 signal_add(&ps->ps_evsigint, NULL);237 signal_add(&ps->ps_evsigterm, NULL);238 signal_add(&ps->ps_evsighup, NULL);239 signal_add(&ps->ps_evsigpipe, NULL);240 signal_add(&ps->ps_evsigusr1, NULL);242 if (!env->gotwebd_noaction)243 proc_connect(ps);245 if (gotwebd_configure(env) == -1)246 fatalx("configuration failed");248 #ifdef PROFILE249 if (unveil("gmon.out", "rwc") != 0)250 err(1, "gmon.out");251 #endif253 if (unveil(strlen(env->httpd_chroot) > 0 ? env->httpd_chroot :254 D_HTTPD_CHROOT, "rwc") == -1)255 err(1, "unveil");257 if (unveil(GOT_TMPDIR_STR, "rw") == -1)258 err(1, "unveil");260 if (unveil(GOTWEBD_CONF, "r") == -1)261 err(1, "unveil");263 if (unveil(NULL, NULL) != 0)264 err(1, "unveil");266 #ifndef PROFILE267 if (pledge("stdio rpath wpath cpath inet unix", NULL) == -1)268 err(1, "pledge");269 #endif271 event_dispatch();273 log_debug("%s gotwebd exiting", getprogname());275 return (0);276 }278 int279 gotwebd_configure(struct gotwebd *env)280 {281 struct server *srv;282 struct socket *sock;283 int id;285 if (env->gotwebd_noaction) {286 fprintf(stderr, "configuration OK\n");287 proc_kill(env->gotwebd_ps);288 exit(0);289 }291 /* gotweb need to reload its config. */292 env->gotwebd_reload = env->prefork_gotwebd;294 /* send our gotweb servers */295 TAILQ_FOREACH(srv, env->servers, entry) {296 if (config_setserver(env, srv) == -1)297 fatalx("%s: send server error", __func__);298 }300 /* send our sockets */301 TAILQ_FOREACH(sock, env->sockets, entry) {302 if (config_setsock(env, sock) == -1)303 fatalx("%s: send socket error", __func__);304 if (config_setfd(env, sock) == -1)305 fatalx("%s: send priv_fd error", __func__);306 }308 for (id = 0; id < PROC_MAX; id++) {309 if (id == privsep_process)310 continue;311 proc_compose(env->gotwebd_ps, id, IMSG_CFG_DONE, NULL, 0);312 }314 return (0);315 }317 void318 gotwebd_configure_done(struct gotwebd *env)319 {320 int id;322 if (env->gotwebd_reload == 0) {323 log_warnx("%s: configuration already finished", __func__);324 return;325 }327 env->gotwebd_reload--;328 if (env->gotwebd_reload == 0) {329 for (id = 0; id < PROC_MAX; id++) {330 if (id == privsep_process)331 continue;332 proc_compose(env->gotwebd_ps, id, IMSG_CTL_START,333 NULL, 0);334 }335 }336 }338 void339 gotwebd_shutdown(void)340 {341 proc_kill(gotwebd_env->gotwebd_ps);343 /* unlink(gotwebd_env->gotweb->gotweb_conf.gotweb_unix_socket_name); */344 /* free(gotwebd_env->gotweb); */345 free(gotwebd_env);347 log_warnx("gotwebd terminating");348 exit(0);349 }