commit 8e5ae9acc3ce865d775ae67f8b5936c400ae07f3 from: Omar Polo date: Fri May 05 19:33:47 2023 UTC msearchd: load the templates like gotmarc(1) commit - 789a106aad27ab1178f8b2420738e39aae6bdf10 commit + 8e5ae9acc3ce865d775ae67f8b5936c400ae07f3 blob - b130fd67c91acce9727918c7af0be8d4aa4787ba blob + 71f274df0de9c93ab7a130bb6af6dee175c6e588 --- msearchd/msearchd.8 +++ msearchd/msearchd.8 @@ -11,6 +11,7 @@ .Op Fl j Ar n .Op Fl p Ar path .Op Fl s Ar socket +.Op Fl t Ar tmpldir .Op Fl u Ar user .Op Ar db .Sh DESCRIPTION @@ -59,6 +60,10 @@ effectively disables the chroot. .It Fl s Ar socket Create an bind to the local socket at .Ar socket . +.It Fl t Ar tmpldir +Path to a directory containing the template files. +.Pa /etc/gotmarc +by default. .It Fl u Ar user Drop privileges to .Ar user @@ -72,7 +77,20 @@ Multiple options increase the verbosity. .El .Sh FILES -.Bl -tag -width /var/www/msearchd/mails.sqlite3 -compact +.Bl -tag -width Ds +.It Pa /etc/gotmarc/foot.html +Template with the trailing part of the page. +.It Pa /etc/gotmarc/head.html +Template with the first part of the page. +.Dv TITLE +is replaced with +.Dq Search . +.It Pa /etc/gotmarc/search-header.html +Template for the start of the search page. +.It Pa /etc/gotmarc/search.html +Template for the search form. +.Dv QUERY +is replaced with the search query. .It Pa /var/www/msearchd/mails.sqite3 Default database. .It Pa /var/www/run/msearchd.sock blob - 7e3e40336b56a84aae1c6b4e109acb0caf2f029b blob + c12aad4bd38910e532fd426187111fb49e8c0cff --- msearchd/msearchd.c +++ msearchd/msearchd.c @@ -37,6 +37,10 @@ #define MSEARCHD_USER "www" #endif +#ifndef MSEARCH_TMPL_DIR +#define MSEARCH_TMPL_DIR "/etc/gotmarc" +#endif + #define MAX_CHILDREN 32 int debug; @@ -44,6 +48,11 @@ int verbose; int children = 3; pid_t pids[MAX_CHILDREN]; +const char *tmpl_head; +const char *tmpl_search; +const char *tmpl_search_header; +const char *tmpl_foot; + __dead void srch_syslog_fatal(int, const char *, ...); __dead void srch_syslog_fatalx(int, const char *, ...); void srch_syslog_warn(const char *, ...); @@ -87,6 +96,40 @@ sighdlr(int sig) errno = save_errno; } +static void +load_tmpl(const char **ret, const char *dir, const char *name) +{ + FILE *fp; + struct stat sb; + char *t; + char path[PATH_MAX]; + int r; + + r = snprintf(path, sizeof(path), "%s/%s", dir, name); + if (r < 0 || (size_t)r >= sizeof(path)) + fatalx("path too long: %s/%s", dir, name); + + if ((fp = fopen(path, "r")) == NULL) + fatal("can't open %s", path); + + if (fstat(fileno(fp), &sb) == -1) + fatal("fstat"); + + if (sb.st_size > SIZE_MAX) + fatal("file too big %s", path); + + if ((t = malloc(sb.st_size + 1)) == NULL) + fatal("malloc"); + + if (fread(t, 1, sb.st_size, fp) != sb.st_size) + fatal("fread %s", path); + + fclose(fp); + + t[sb.st_size] = '\0'; + *ret = t; +} + static int bind_socket(const char *path, struct passwd *pw) { @@ -149,9 +192,9 @@ bind_socket(const char *path, struct passwd *pw) static pid_t start_child(const char *argv0, const char *root, const char *user, - const char *db, int debug, int verbose, int fd) + const char *db, const char *tmpl, int debug, int verbose, int fd) { - const char *argv[11]; + const char *argv[13]; int argc = 0; pid_t pid; @@ -174,6 +217,7 @@ start_child(const char *argv0, const char *root, const argv[argc++] = argv0; argv[argc++] = "-S"; argv[argc++] = "-p"; argv[argc++] = root; + argv[argc++] = "-t"; argv[argc++] = tmpl; argv[argc++] = "-u"; argv[argc++] = user; if (debug) argv[argc++] = "-d"; @@ -192,8 +236,8 @@ start_child(const char *argv0, const char *root, const static void __dead usage(void) { - fprintf(stderr, - "usage: %s [-dv] [-j n] [-p path] [-s socket] [-u user] [db]\n", + fprintf(stderr, "usage: %s [-dv] [-j n] [-p path] [-s socket]" + " [-t tmpldir] [-u user] [db]\n", getprogname()); exit(1); } @@ -208,6 +252,7 @@ main(int argc, char **argv) const char *user = MSEARCHD_USER; const char *root = NULL; const char *db = MSEARCHD_DB; + const char *tmpldir = MSEARCH_TMPL_DIR; const char *errstr, *cause, *argv0; pid_t pid; int ch, i, fd, ret, status, server = 0; @@ -231,7 +276,7 @@ main(int argc, char **argv) if ((argv0 = argv[0]) == NULL) argv0 = "msearchd"; - while ((ch = getopt(argc, argv, "dj:p:Ss:u:v")) != -1) { + while ((ch = getopt(argc, argv, "dj:p:Ss:t:u:v")) != -1) { switch (ch) { case 'd': debug = 1; @@ -251,6 +296,9 @@ main(int argc, char **argv) case 's': sock = optarg; break; + case 't': + tmpldir = optarg; + break; case 'u': user = optarg; break; @@ -309,8 +357,8 @@ main(int argc, char **argv) if ((d = dup(fd)) == -1) fatalx("dup"); - pids[i] = start_child(argv0, root, user, db, debug, - verbose, d); + pids[i] = start_child(argv0, root, user, db, tmpldir, + debug, verbose, d); log_debug("forking child %d (pid %lld)", i, (long long)pids[i]); } @@ -321,6 +369,11 @@ main(int argc, char **argv) signal(SIGHUP, SIG_IGN); sigprocmask(SIG_UNBLOCK, &set, NULL); + } else { + load_tmpl(&tmpl_head, tmpldir, "head.html"); + load_tmpl(&tmpl_search, tmpldir, "search.html"); + load_tmpl(&tmpl_search_header, tmpldir, "search-header.html"); + load_tmpl(&tmpl_foot, tmpldir, "foot.html"); } if (chroot(root) == -1) blob - 47503ed5c28b0c755cf05499e59e260a30933d5f blob + e0ac0be5e89e31a03ddc36507791c0320adef3f9 --- msearchd/msearchd.h +++ msearchd/msearchd.h @@ -108,6 +108,12 @@ int clt_printf(struct client *, const char *, ...) int fcgi_cmp(struct fcgi *, struct fcgi *); int fcgi_client_cmp(struct client *, struct client *); +/* msearchd.c */ +extern const char *tmpl_head; +extern const char *tmpl_search; +extern const char *tmpl_search_header; +extern const char *tmpl_foot; + /* server.c */ int server_main(const char *); int server_handle(struct env *, struct client *); blob - cd75c40c656b6516755731f7714583f76ba56c51 blob + 9a533b7f961b04d3bd636c5dd42247025b4701c7 --- msearchd/server.c +++ msearchd/server.c @@ -272,6 +272,27 @@ fts_escape(const char *p, char *buf, size_t bufsize) return (-1); } +static int +render_tmpl(struct client *clt, const char *tmpl, + const char *var, const char *val) +{ + const char *t; + size_t vlen; + + if (var == NULL) + return (clt_puts(clt, tmpl)); + + vlen = strlen(var); + while ((t = strstr(tmpl, var)) != NULL) { + if (clt_write(clt, tmpl, t - tmpl) == -1 || + clt_putsan(clt, val) == -1) + return (-1); + tmpl = t + vlen; + } + + return (clt_puts(clt, tmpl)); +} + int server_handle(struct env *env, struct client *clt) { @@ -304,37 +325,11 @@ server_handle(struct env *env, struct client *clt) if (server_reply(clt, 200, "text/html") == -1) goto err; - if (clt_puts(clt, "" - "" - "" - "" - "" - "" - "Game of Trees Mail Archive | Search" - "" - "" - "
" - "" - "\"GOT\" where the \"O\" is a cute, smiling pufferfish" - "" - "

Game of Trees Mail Archive

" - "
") == -1) + if (render_tmpl(clt, tmpl_head, "TITLE", "Search") == -1 || + render_tmpl(clt, tmpl_search_header, NULL, NULL) == -1 || + render_tmpl(clt, tmpl_search, "QUERY", query) == -1) goto err; - if (clt_puts(clt, "" - "
" - "" - " " - "
") == -1) - goto err; - if (query == NULL) goto done; @@ -398,7 +393,7 @@ server_handle(struct env *env, struct client *clt) goto err; done: - if (clt_puts(clt, "\n") == -1) + if (render_tmpl(clt, tmpl_foot, NULL, NULL) == -1) goto err; sqlite3_reset(env->env_query); blob - /dev/null blob + b850ad407bec9a23b378dec5f925cf7bcaa8ec7a (mode 644) --- /dev/null +++ templates/search-header.html @@ -0,0 +1,11 @@ +
+ + "GOT" where the "O" is a cute smiling pufferfish. + +

Game of Trees Mail Archive

+
+