commit - 4fd3ab65db81313a54815adef56b05709e08fce6
commit + 8b10295ec9ddde4f3bfef322b31d3601d6040c62
blob - dfaea693e455367a6ee8fea158b8dbdfa779fed7
blob + 1210e46dd5c67d6073935d5542ac84dc5a6f6a15
--- gotd/gotd.c
+++ gotd/gotd.c
fatal("socketpair");
memset(&ireq, 0, sizeof(ireq));
+ if (strlcpy(ireq.repo_name, repo_proc->repo_name,
+ sizeof(ireq.repo_name)) >= sizeof(ireq.repo_name)) {
+ err = got_error_msg(GOT_ERR_NO_SPACE,
+ "repository name too long");
+ close(pipe[0]);
+ close(pipe[1]);
+ return err;
+ }
ireq.proc_id = repo_proc->type;
/* Pass repo child pipe to session child process. */
execvp(argv[0], (char * const *)argv);
fatal("execvp");
+}
+
+static const struct got_error *
+send_pathlist_elem(struct gotd_imsgev *iev, const char *refname, int imsg_type)
+{
+ struct gotd_imsg_pathlist_elem ielem;
+ struct ibuf *wbuf = NULL;
+
+ memset(&ielem, 0, sizeof(ielem));
+ ielem.path_len = strlen(refname);
+
+ wbuf = imsg_create(&iev->ibuf, imsg_type, GOTD_PROC_GOTD, gotd.pid,
+ sizeof(ielem) + ielem.path_len);
+ if (wbuf == NULL)
+ return got_error_from_errno_fmt("imsg_create %d", imsg_type);
+
+ if (imsg_add(wbuf, &ielem, sizeof(ielem)) == -1)
+ return got_error_from_errno_fmt("imsg_add %d", imsg_type);
+ if (imsg_add(wbuf, refname, ielem.path_len) == -1)
+ return got_error_from_errno_fmt("imsg_add %d", imsg_type);
+
+ imsg_close(&iev->ibuf, wbuf);
+ return gotd_imsg_flush(&iev->ibuf);
+}
+
+static const struct got_error *
+send_request_timeout(struct gotd_imsgev *iev, struct timeval *timeout)
+{
+ if (gotd_imsg_compose_event(iev, GOTD_IMSG_REQUEST_TIMEOUT,
+ GOTD_PROC_GOTD, -1, timeout, sizeof(*timeout)) == -1) {
+ return got_error_from_errno("imsg compose REQUEST_TIMEOUT");
+ }
+
+ return NULL;
+}
+
+static const struct got_error *
+send_notification_target_email(struct gotd_imsgev *iev,
+ struct gotd_notification_target *target)
+{
+ struct gotd_imsg_notitfication_target_email itarget;
+ struct ibuf *wbuf = NULL;
+
+ memset(&itarget, 0, sizeof(itarget));
+
+ if (target->conf.email.sender)
+ itarget.sender_len = strlen(target->conf.email.sender);
+ if (target->conf.email.recipient)
+ itarget.recipient_len = strlen(target->conf.email.recipient);
+ if (target->conf.email.responder)
+ itarget.responder_len = strlen(target->conf.email.responder);
+ if (target->conf.email.hostname)
+ itarget.hostname_len = strlen(target->conf.email.hostname);
+ if (target->conf.email.port)
+ itarget.port_len = strlen(target->conf.email.port);
+
+ wbuf = imsg_create(&iev->ibuf, GOTD_IMSG_NOTIFICATION_TARGET_EMAIL,
+ 0, 0, sizeof(itarget) + itarget.sender_len + itarget.recipient_len +
+ itarget.responder_len + itarget.hostname_len + itarget.port_len);
+ if (wbuf == NULL) {
+ return got_error_from_errno("imsg_create "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+
+ if (imsg_add(wbuf, &itarget, sizeof(itarget)) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ if (target->conf.email.sender) {
+ if (imsg_add(wbuf, target->conf.email.sender,
+ itarget.sender_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ }
+ if (target->conf.email.recipient) {
+ if (imsg_add(wbuf, target->conf.email.recipient,
+ itarget.recipient_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ }
+ if (target->conf.email.responder) {
+ if (imsg_add(wbuf, target->conf.email.responder,
+ itarget.responder_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ }
+ if (target->conf.email.hostname) {
+ if (imsg_add(wbuf, target->conf.email.hostname,
+ itarget.hostname_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ }
+ if (target->conf.email.port) {
+ if (imsg_add(wbuf, target->conf.email.port,
+ itarget.port_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_EMAIL");
+ }
+ }
+
+ imsg_close(&iev->ibuf, wbuf);
+ return gotd_imsg_flush(&iev->ibuf);
}
+static const struct got_error *
+send_notification_target_http(struct gotd_imsgev *iev,
+ struct gotd_notification_target *target)
+{
+ struct gotd_imsg_notitfication_target_http itarget;
+ struct ibuf *wbuf = NULL;
+
+ memset(&itarget, 0, sizeof(itarget));
+
+ itarget.tls = target->conf.http.tls;
+ itarget.hostname_len = strlen(target->conf.http.hostname);
+ itarget.port_len = strlen(target->conf.http.port);
+ itarget.path_len = strlen(target->conf.http.path);
+ if (target->conf.http.auth)
+ itarget.auth_len = strlen(target->conf.http.auth);
+ if (target->conf.http.hmac)
+ itarget.hmac_len = strlen(target->conf.http.hmac);
+
+ wbuf = imsg_create(&iev->ibuf, GOTD_IMSG_NOTIFICATION_TARGET_HTTP,
+ 0, 0, sizeof(itarget) + itarget.hostname_len + itarget.port_len +
+ itarget.path_len + itarget.auth_len + itarget.hmac_len);
+ if (wbuf == NULL) {
+ return got_error_from_errno("imsg_create "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+
+ if (imsg_add(wbuf, &itarget, sizeof(itarget)) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+ if (imsg_add(wbuf, target->conf.http.hostname,
+ itarget.hostname_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+ if (imsg_add(wbuf, target->conf.http.port,
+ itarget.port_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+ if (imsg_add(wbuf, target->conf.http.path,
+ itarget.path_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+
+ if (target->conf.http.auth) {
+ if (imsg_add(wbuf, target->conf.http.auth,
+ itarget.auth_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+ }
+ if (target->conf.http.hmac) {
+ if (imsg_add(wbuf, target->conf.http.hmac,
+ itarget.hmac_len) == -1) {
+ return got_error_from_errno("imsg_add "
+ "NOTIFICATION_TARGET_HTTP");
+ }
+ }
+
+ imsg_close(&iev->ibuf, wbuf);
+ return gotd_imsg_flush(&iev->ibuf);
+}
+
+static const struct got_error *
+send_notification_target(struct gotd_imsgev *iev,
+ struct gotd_notification_target *target)
+{
+ const struct got_error *err = NULL;
+
+ switch (target->type) {
+ case GOTD_NOTIFICATION_VIA_EMAIL:
+ err = send_notification_target_email(iev, target);
+ break;
+ case GOTD_NOTIFICATION_VIA_HTTP:
+ err = send_notification_target_http(iev, target);
+ break;
+ default:
+ log_warn("unsupported notification target type %d",
+ target->type);
+ break;
+ }
+
+ return err;
+}
+
+static const struct got_error *
+send_notification_config(struct gotd_imsgev *iev, char *repo_name)
+{
+ const struct got_error *err = NULL;
+ struct gotd_repo *repo;
+ struct got_pathlist_entry *pe;
+ struct gotd_imsg_pathlist ilist;
+ struct gotd_notification_target *target;
+
+ memset(&ilist, 0, sizeof(ilist));
+
+ repo = gotd_find_repo_by_name(repo_name, &gotd.repos);
+ if (repo == NULL)
+ return got_error(GOT_ERR_NOT_GIT_REPO);
+
+ ilist.nelem = repo->num_notification_refs;
+ if (ilist.nelem > 0) {
+ if (gotd_imsg_compose_event(iev, GOTD_IMSG_NOTIFICATION_REFS,
+ GOTD_PROC_GOTD, -1, &ilist, sizeof(ilist)) == -1) {
+ return got_error_from_errno("imsg compose "
+ "NOTIFICATION_REFS");
+ }
+
+ RB_FOREACH(pe, got_pathlist_head, &repo->notification_refs) {
+ err = send_pathlist_elem(iev, pe->path,
+ GOTD_IMSG_NOTIFICATION_REFS_ELEM);
+ if (err)
+ return err;
+ }
+ }
+
+ ilist.nelem = repo->num_notification_ref_namespaces;
+ if (ilist.nelem > 0) {
+ if (gotd_imsg_compose_event(iev,
+ GOTD_IMSG_NOTIFICATION_REF_NAMESPACES,
+ GOTD_PROC_GOTD, -1, &ilist, sizeof(ilist)) == -1) {
+ return got_error_from_errno("imsg compose "
+ "NOTIFICATION_REF_NAMESPACES");
+ }
+
+ RB_FOREACH(pe, got_pathlist_head,
+ &repo->notification_ref_namespaces) {
+ err = send_pathlist_elem(iev, pe->path,
+ GOTD_IMSG_NOTIFICATION_REF_NAMESPACES_ELEM);
+ if (err)
+ return err;
+ }
+ }
+
+ STAILQ_FOREACH(target, &repo->notification_targets, entry) {
+ err = send_notification_target(iev, target);
+ if (err)
+ return err;
+ }
+
+ return NULL;
+}
+
static void
gotd_dispatch_client_session(int fd, short event, void *arg)
{
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
+ if (client_is_writing(client)) {
+ err = send_request_timeout(iev,
+ &gotd.request_timeout);
+ if (err)
+ break;
+ err = send_notification_config(iev,
+ proc->repo_name);
+ if (err)
+ break;
+ }
do_start_repo_child = 1;
break;
case GOTD_IMSG_RUN_GOTSYS_CHECK:
}
return NULL;
-}
-
-static const struct got_error *
-send_protected_ref(struct gotd_imsgev *iev, const char *refname,
- int imsg_type)
-{
- struct gotd_imsg_pathlist_elem ielem;
- struct ibuf *wbuf = NULL;
-
- memset(&ielem, 0, sizeof(ielem));
- ielem.path_len = strlen(refname);
-
- wbuf = imsg_create(&iev->ibuf, imsg_type, GOTD_PROC_GOTD, gotd.pid,
- sizeof(ielem) + ielem.path_len);
- if (wbuf == NULL)
- return got_error_from_errno_fmt("imsg_create %d", imsg_type);
-
- if (imsg_add(wbuf, &ielem, sizeof(ielem)) == -1)
- return got_error_from_errno_fmt("imsg_add %d", imsg_type);
- if (imsg_add(wbuf, refname, ielem.path_len) == -1)
- return got_error_from_errno_fmt("imsg_add %d", imsg_type);
-
- imsg_close(&iev->ibuf, wbuf);
- return gotd_imsg_flush(&iev->ibuf);
}
static const struct got_error *
RB_FOREACH(pe, got_pathlist_head,
&repo->protected_tag_namespaces) {
- err = send_protected_ref(iev, pe->path,
+ err = send_pathlist_elem(iev, pe->path,
GOTD_IMSG_PROTECTED_TAG_NAMESPACES_ELEM);
if (err)
return err;
RB_FOREACH(pe, got_pathlist_head,
&repo->protected_branch_namespaces) {
- err = send_protected_ref(iev, pe->path,
+ err = send_pathlist_elem(iev, pe->path,
GOTD_IMSG_PROTECTED_BRANCH_NAMESPACES_ELEM);
if (err)
return err;
}
RB_FOREACH(pe, got_pathlist_head, &repo->protected_branches) {
- err = send_protected_ref(iev, pe->path,
+ err = send_pathlist_elem(iev, pe->path,
GOTD_IMSG_PROTECTED_BRANCHES_ELEM);
if (err)
return err;
}
if (proc_id != GOTD_PROC_LISTEN && proc_id != GOTD_PROC_AUTH &&
- proc_id != GOTD_PROC_REPO_WRITE) {
+ proc_id != GOTD_PROC_REPO_WRITE &&
+ proc_id != GOTD_PROC_SESSION_WRITE) {
if (gotd_parse_config(confpath, proc_id, secrets, &gotd) != 0)
return 1;
err(1, "pledge");
#endif
apply_unveil_repo_readwrite(repo_path);
- repo = gotd_find_repo_by_path(repo_path, &gotd);
- if (repo == NULL)
- fatalx("no repository for path %s", repo_path);
- session_write_main(title, repo_path, pack_fds, temp_fds, tmp_fd,
- &gotd.request_timeout, repo);
+ session_write_main(title, repo_path, pack_fds, temp_fds,
+ tmp_fd);
/* NOTREACHED */
break;
case GOTD_PROC_REPO_READ:
blob - bc67d2befa7742192232f3c52b8845a86648e643
blob + 95ebcef04adc3f9d2afc5df131874ee0f9170ed7
--- gotd/gotd.h
+++ gotd/gotd.h
size_t nprotected_branches;
struct got_pathlist_head notification_refs;
+ size_t num_notification_refs;
struct got_pathlist_head notification_ref_namespaces;
+ size_t num_notification_ref_namespaces;
struct gotd_notification_targets notification_targets;
};
TAILQ_HEAD(gotd_repolist, gotd_repo);
GOTD_IMSG_LISTENER_READY,
GOTD_IMSG_LISTEN_SOCKET,
GOTD_IMSG_CONNECTION_LIMIT,
+ GOTD_IMSG_REQUEST_TIMEOUT,
GOTD_IMSG_DISCONNECT,
GOTD_IMSG_CONNECT,
GOTD_IMSG_PROTECTED_BRANCHES_ELEM,
/* Notify child process. */
+ GOTD_IMSG_NOTIFICATION_REFS,
+ GOTD_IMSG_NOTIFICATION_REFS_ELEM,
+ GOTD_IMSG_NOTIFICATION_REF_NAMESPACES,
+ GOTD_IMSG_NOTIFICATION_REF_NAMESPACES_ELEM,
+ GOTD_IMSG_NOTIFICATION_TARGET_EMAIL,
+ GOTD_IMSG_NOTIFICATION_TARGET_HTTP,
GOTD_IMSG_CONNECT_NOTIFIER,
GOTD_IMSG_CONNECT_SESSION,
GOTD_IMSG_NOTIFY,
/* Structure for GOTD_IMSG_CONNECT_REPO_CHILD. */
struct gotd_imsg_connect_repo_child {
+ char repo_name[NAME_MAX];
enum gotd_procid proc_id;
/* repo child imsg pipe is passed via imsg fd */
* GOTD_IMSG_PROTECTED_TAG_NAMESPACES
* GOTD_IMSG_PROTECTED_BRANCH_NAMESPACES
* GOTD_IMSG_PROTECTED_BRANCHES
+ * GOTD_IMSG_NOTIFY_BRANCHES
+ * GOTD_IMSG_NOTIFY_REF_NAMESPACES
*/
struct gotd_imsg_pathlist {
size_t nelem;
* GOTD_IMSG_PROTECTED_TAG_NAMESPACES_ELEM
* GOTD_IMSG_PROTECTED_BRANCH_NAMESPACES_ELEM
* GOTD_IMSG_PROTECTED_BRANCHES_ELEM
+ * GOTD_IMSG_NOTIFY_BRANCHES_ELEM
+ * GOTD_IMSG_NOTIFY_REF_NAMESPACES_ELEM
*/
struct gotd_imsg_pathlist_elem {
size_t path_len;
/* Followed by path_len bytes. */
/* Followed by data_len bytes. */
+};
+
+/* Structure for GOTD_IMSG_NOTIFICATION_TARGET_EMAIL. */
+struct gotd_imsg_notitfication_target_email {
+ size_t sender_len;
+ size_t recipient_len;
+ size_t responder_len;
+ size_t hostname_len;
+ size_t port_len;
+
+ /*
+ * Followed by sender_len + responder_len + responder_len +
+ * hostname_len + port_len bytes.
+ */
};
+/* Structure for GOTD_IMSG_NOTIFICATION_TARGET_HTTP. */
+struct gotd_imsg_notitfication_target_http {
+ int tls;
+ size_t hostname_len;
+ size_t port_len;
+ size_t path_len;
+ size_t auth_len;
+ size_t hmac_len;;
+
+ /*
+ * Followed by hostname_len + port_len + path_len + auth_len +
+ * hmac_len bytes.
+ */
+};
+
/* Structures for GOTD_IMSG_NOTIFY. */
enum gotd_notification_action {
GOTD_NOTIF_ACTION_CREATED,
uint32_t, pid_t);
void gotd_imsg_send_nak(struct got_object_id *, struct imsgbuf *,
uint32_t, pid_t);
+const struct got_error *gotd_imsg_recv_pathlist(size_t *, struct imsg *);
+const struct got_error *gotd_imsg_recv_pathlist_elem(struct imsg *,
+ struct got_pathlist_head *);
blob - 476171315d6b76a7222751f268472e1275f1373b
blob + e0c130803906829b51d5f392e75336ea4f953991
--- gotd/imsg.c
+++ gotd/imsg.c
#include <limits.h>
#include <poll.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
return gotd_imsg_compose_event(iev, imsg->hdr.type, imsg->hdr.peerid,
fd, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
}
+
+const struct got_error *
+gotd_imsg_recv_pathlist(size_t *npaths, struct imsg *imsg)
+{
+ struct gotd_imsg_pathlist ilist;
+ size_t datalen;
+
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ if (datalen != sizeof(ilist))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ memcpy(&ilist, imsg->data, sizeof(ilist));
+
+ if (ilist.nelem == 0)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ *npaths = ilist.nelem;
+ return NULL;
+}
+
+const struct got_error *
+gotd_imsg_recv_pathlist_elem(struct imsg *imsg, struct got_pathlist_head *paths)
+{
+ const struct got_error *err = NULL;
+ struct gotd_imsg_pathlist_elem ielem;
+ size_t datalen;
+ char *path;
+ struct got_pathlist_entry *pe;
+
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ if (datalen < sizeof(ielem))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ memcpy(&ielem, imsg->data, sizeof(ielem));
+
+ if (datalen != sizeof(ielem) + ielem.path_len)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ path = strndup(imsg->data + sizeof(ielem), ielem.path_len);
+ if (path == NULL)
+ return got_error_from_errno("strndup");
+
+ err = got_pathlist_insert(&pe, paths, path, NULL);
+ if (err || pe == NULL)
+ free(path);
+ return err;
+}
+
blob - 4bf1400741232fd1549cacb7f3b0cd4cdd95cf25
blob + daaf2c2aa310ab499970f60fa62149dff6b06347
--- gotd/parse.y
+++ gotd/parse.y
notifyflags : BRANCH STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_branch(new_repo, $2)) {
free($2);
}
| REFERENCE NAMESPACE STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_ref_namespace(new_repo, $3)) {
free($3);
}
| EMAIL TO STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
NULL, NULL, NULL)) {
}
| EMAIL FROM STRING TO STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
NULL, NULL, NULL)) {
}
| EMAIL TO STRING REPLY TO STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
$6, NULL, NULL)) {
}
| EMAIL FROM STRING TO STRING REPLY TO STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
$8, NULL, NULL)) {
}
| EMAIL TO STRING RELAY STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
NULL, $5, NULL)) {
}
| EMAIL FROM STRING TO STRING RELAY STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
NULL, $7, NULL)) {
}
| EMAIL TO STRING REPLY TO STRING RELAY STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
$6, $8, NULL)) {
}
| EMAIL FROM STRING TO STRING REPLY TO STRING RELAY STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
$8, $10, NULL)) {
}
| EMAIL TO STRING RELAY STRING PORT STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
NULL, $5, $7)) {
}
| EMAIL FROM STRING TO STRING RELAY STRING PORT STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
NULL, $7, $9)) {
}
| EMAIL TO STRING REPLY TO STRING RELAY STRING PORT STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
$6, $8, $10)) {
}
| EMAIL FROM STRING TO STRING REPLY TO STRING RELAY STRING PORT STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
$8, $10, $12)) {
}
| EMAIL TO STRING RELAY STRING PORT NUMBER {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
NULL, $5, port_sprintf($7))) {
}
| EMAIL FROM STRING TO STRING RELAY STRING PORT NUMBER {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
NULL, $7, port_sprintf($9))) {
}
| EMAIL TO STRING REPLY TO STRING RELAY STRING PORT NUMBER {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, NULL, $3,
$6, $8, port_sprintf($10))) {
}
| EMAIL FROM STRING TO STRING REPLY TO STRING RELAY STRING PORT NUMBER {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_email(new_repo, $3, $5,
$8, $10, port_sprintf($12))) {
}
| URL STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, NULL,
NULL, 0)) {
}
| URL STRING AUTH STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, $4, NULL,
0)) {
}
| URL STRING AUTH STRING INSECURE {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, $4, NULL,
1)) {
}
| URL STRING HMAC STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, NULL, $4,
0)) {
}
| URL STRING AUTH STRING HMAC STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, $4, $6,
0)) {
}
| URL STRING AUTH STRING INSECURE HMAC STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (conf_notify_http(new_repo, $2, $4, $7,
1)) {
}
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_GITWRAPPER |
gotd_proc_id == GOTD_PROC_NOTIFY) {
new_repo = conf_new_repo($2);
repoopts1 : PATH STRING {
if (gotd_proc_id == GOTD_PROC_GOTD ||
- gotd_proc_id == GOTD_PROC_SESSION_WRITE ||
gotd_proc_id == GOTD_PROC_GITWRAPPER ||
gotd_proc_id == GOTD_PROC_NOTIFY) {
if (!got_path_is_absolute($2)) {
}
if (pe == NULL)
free(refname);
+ else
+ repo->num_notification_refs++;
return 0;
}
}
if (pe == NULL)
free(s);
+ else
+ repo->num_notification_ref_namespaces++;
return 0;
}
blob - 7d8e2cf8d5bc2251c71eadad35e0d5e810910b00
blob + 219767f09e11b7fc1231a8076ebabe3276c1fb22
--- gotd/repo_write.c
+++ gotd/repo_write.c
event_set(&iev->ev, iev->ibuf.fd, EV_READ,
repo_write_dispatch_session, iev);
gotd_imsg_event_add(iev);
-
- return NULL;
-}
-
-static const struct got_error *
-recv_pathlist(size_t *npaths, struct imsg *imsg)
-{
- struct gotd_imsg_pathlist ilist;
- size_t datalen;
-
- datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
- if (datalen != sizeof(ilist))
- return got_error(GOT_ERR_PRIVSEP_LEN);
- memcpy(&ilist, imsg->data, sizeof(ilist));
- if (ilist.nelem == 0)
- return got_error(GOT_ERR_PRIVSEP_LEN);
-
- *npaths = ilist.nelem;
return NULL;
}
-static const struct got_error *
-recv_pathlist_elem(struct imsg *imsg, struct got_pathlist_head *paths)
-{
- const struct got_error *err = NULL;
- struct gotd_imsg_pathlist_elem ielem;
- size_t datalen;
- char *path;
- struct got_pathlist_entry *pe;
-
- datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
- if (datalen < sizeof(ielem))
- return got_error(GOT_ERR_PRIVSEP_LEN);
- memcpy(&ielem, imsg->data, sizeof(ielem));
-
- if (datalen != sizeof(ielem) + ielem.path_len)
- return got_error(GOT_ERR_PRIVSEP_LEN);
-
- path = strndup(imsg->data + sizeof(ielem), ielem.path_len);
- if (path == NULL)
- return got_error_from_errno("strndup");
-
- err = got_pathlist_insert(&pe, paths, path, NULL);
- if (err || pe == NULL)
- free(path);
- return err;
-}
-
static void
repo_write_dispatch(int fd, short event, void *arg)
{
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
- err = recv_pathlist(&npaths, &imsg);
+ err = gotd_imsg_recv_pathlist(&npaths, &imsg);
if (err)
break;
repo_write.protected_refs_cur =
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
- err = recv_pathlist(&npaths, &imsg);
+ err = gotd_imsg_recv_pathlist(&npaths, &imsg);
if (err)
break;
repo_write.protected_refs_cur =
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
- err = recv_pathlist(&npaths, &imsg);
+ err = gotd_imsg_recv_pathlist(&npaths, &imsg);
if (err)
break;
repo_write.protected_refs_cur =
err = got_error(GOT_ERR_PRIVSEP_MSG);
break;
}
- err = recv_pathlist_elem(&imsg,
+ err = gotd_imsg_recv_pathlist_elem(&imsg,
repo_write.protected_refs_cur);
if (err)
break;
blob - 013664a6ec707d98777ecf00c0180d760ca947d7
blob + d139091dacf9e073b2a167c8dca8537a36c7c461
--- gotd/session_write.c
+++ gotd/session_write.c
pid_t pid;
const char *title;
struct got_repository *repo;
- struct gotd_repo *repo_cfg;
+ char repo_name[NAME_MAX];
int *pack_fds;
int *temp_fds;
int content_fd;
struct timeval request_timeout;
enum gotd_session_write_state state;
struct gotd_imsgev repo_child_iev;
+ struct got_pathlist_head notification_refs;
+ struct got_pathlist_head notification_ref_namespaces;
+ size_t num_notification_refs_needed;
+ size_t num_notification_refs_received;
+ struct got_pathlist_head *notification_refs_cur;
+ struct gotd_notification_targets notification_targets;
} gotd_session;
static struct gotd_session_client {
static int
need_packfile_verification(void)
{
- return (strcmp(gotd_session.repo_cfg->name, "gotsys") == 0 ||
- strcmp(gotd_session.repo_cfg->name, "gotsys.git") == 0);
+ return (strcmp(gotd_session.repo_name, "gotsys") == 0 ||
+ strcmp(gotd_session.repo_name, "gotsys.git") == 0);
}
static const struct got_error *
struct got_repository *repo, struct got_reference *ref)
{
const struct got_error *err = NULL;
- struct gotd_repo *repo_cfg = gotd_session.repo_cfg;
struct gotd_imsgev *iev = &gotd_session.repo_child_iev;
struct got_pathlist_entry *pe;
struct gotd_session_notif *notif;
if (iev->ibuf.fd == -1 ||
- STAILQ_EMPTY(&repo_cfg->notification_targets))
+ STAILQ_EMPTY(&gotd_session.notification_targets))
return NULL; /* notifications unused */
- RB_FOREACH(pe, got_pathlist_head, &repo_cfg->notification_refs) {
+ RB_FOREACH(pe, got_pathlist_head, &gotd_session.notification_refs) {
const char *refname = pe->path;
if (strcmp(got_ref_get_name(ref), refname) == 0)
break;
}
if (pe == NULL) {
RB_FOREACH(pe, got_pathlist_head,
- &repo_cfg->notification_ref_namespaces) {
+ &gotd_session.notification_ref_namespaces) {
const char *namespace = pe->path;
err = validate_namespace(namespace);
* configuration file then only send notifications if a match
* was found.
*/
- if (pe == NULL && (!RB_EMPTY(&repo_cfg->notification_refs) ||
- !RB_EMPTY(&repo_cfg->notification_ref_namespaces)))
+ if (pe == NULL && (!RB_EMPTY(&gotd_session.notification_refs) ||
+ !RB_EMPTY(&gotd_session.notification_ref_namespaces)))
return NULL;
notif = calloc(1, sizeof(*notif));
goto done;
}
- strlcpy(inotify.repo_name, gotd_session.repo_cfg->name,
+ strlcpy(inotify.repo_name, gotd_session.repo_name,
sizeof(inotify.repo_name));
snprintf(inotify.subject_line, sizeof(inotify.subject_line),
- "%s: %s %s %s: %.12s", gotd_session.repo_cfg->name,
+ "%s: %s %s %s: %.12s", gotd_session.repo_name,
client->username, action, notif->refname, id_str);
inotify.username_len = strlen(client->username);
fd = imsg_get_fd(imsg);
if (fd == -1)
return got_error(GOT_ERR_PRIVSEP_NO_FD);
+
+ if (strlcpy(gotd_session.repo_name, ichild.repo_name,
+ sizeof(gotd_session.repo_name)) >= sizeof(gotd_session.repo_name)) {
+ return got_error_msg(GOT_ERR_NO_SPACE,
+ "repository name too long");
+ }
if (imsgbuf_init(&gotd_session.repo_child_iev.ibuf, fd) == -1) {
close(fd);
}
static void
+free_notification_target(struct gotd_notification_target *target)
+{
+ if (target == NULL)
+ return;
+
+ switch (target->type) {
+ case GOTD_NOTIFICATION_VIA_EMAIL:
+ free(target->conf.email.sender);
+ free(target->conf.email.recipient);
+ free(target->conf.email.responder);
+ free(target->conf.email.hostname);
+ free(target->conf.email.port);
+ break;
+ case GOTD_NOTIFICATION_VIA_HTTP:
+ free(target->conf.http.hostname);
+ free(target->conf.http.port);
+ free(target->conf.http.path);
+ free(target->conf.http.auth);
+ free(target->conf.http.hmac);
+ break;
+ default:
+ break;
+ }
+
+ free(target);
+}
+
+static const struct got_error *
+recv_notification_target_email(struct imsg *imsg)
+{
+ const struct got_error *err = NULL;
+ struct gotd_imsg_notitfication_target_email itarget;
+ struct gotd_notification_target *target;
+ size_t datalen;
+
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ if (datalen < sizeof(itarget))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ memcpy(&itarget, imsg->data, sizeof(itarget));
+
+ if (datalen != sizeof(itarget) + itarget.sender_len +
+ itarget.recipient_len + itarget.responder_len +
+ itarget.hostname_len + itarget.port_len)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ if (itarget.recipient_len == 0)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ target = calloc(1, sizeof(*target));
+ if (target == NULL)
+ return got_error_from_errno("calloc");
+
+ target->type = GOTD_NOTIFICATION_VIA_EMAIL;
+
+ if (itarget.sender_len) {
+ target->conf.email.sender = strndup(imsg->data +
+ sizeof(itarget), itarget.sender_len);
+ if (target->conf.email.sender == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.email.sender) != itarget.sender_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ target->conf.email.recipient = strndup(imsg->data + sizeof(itarget) +
+ itarget.sender_len, itarget.recipient_len);
+ if (target->conf.email.recipient == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.email.recipient) != itarget.recipient_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+
+ if (itarget.responder_len) {
+ target->conf.email.responder = strndup(imsg->data +
+ sizeof(itarget) + itarget.sender_len + itarget.recipient_len,
+ itarget.responder_len);
+ if (target->conf.email.responder == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.email.responder) !=
+ itarget.responder_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ if (itarget.hostname_len) {
+ target->conf.email.hostname = strndup(imsg->data +
+ sizeof(itarget) + itarget.sender_len +
+ itarget.recipient_len + itarget.responder_len,
+ itarget.hostname_len);
+ if (target->conf.email.hostname == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.email.hostname) !=
+ itarget.hostname_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ if (itarget.port_len) {
+ target->conf.email.port = strndup(imsg->data +
+ sizeof(itarget) + itarget.sender_len +
+ itarget.recipient_len + itarget.responder_len +
+ itarget.hostname_len, itarget.port_len);
+ if (target->conf.email.port == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.email.port) != itarget.port_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ STAILQ_INSERT_TAIL(&gotd_session.notification_targets, target, entry);
+ target = NULL;
+done:
+ if (err)
+ free_notification_target(target);
+ return err;
+}
+
+static const struct got_error *
+recv_notification_target_http(struct imsg *imsg)
+{
+ const struct got_error *err = NULL;
+ struct gotd_imsg_notitfication_target_http itarget;
+ struct gotd_notification_target *target;
+ size_t datalen;
+
+ datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ if (datalen < sizeof(itarget))
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+ memcpy(&itarget, imsg->data, sizeof(itarget));
+
+ if (datalen != sizeof(itarget) + itarget.hostname_len +
+ itarget.port_len + itarget.path_len + itarget.auth_len +
+ itarget.hmac_len)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ if (itarget.hostname_len == 0 || itarget.port_len == 0 ||
+ itarget.path_len == 0)
+ return got_error(GOT_ERR_PRIVSEP_LEN);
+
+ target = calloc(1, sizeof(*target));
+ if (target == NULL)
+ return got_error_from_errno("calloc");
+
+ target->type = GOTD_NOTIFICATION_VIA_HTTP;
+
+ target->conf.http.tls = itarget.tls;
+
+ target->conf.http.hostname = strndup(imsg->data +
+ sizeof(itarget), itarget.hostname_len);
+ if (target->conf.http.hostname == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.http.hostname) != itarget.hostname_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+
+ target->conf.http.port = strndup(imsg->data + sizeof(itarget) +
+ itarget.hostname_len, itarget.port_len);
+ if (target->conf.http.port == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.http.port) != itarget.port_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+
+ target->conf.http.path = strndup(imsg->data +
+ sizeof(itarget) + itarget.hostname_len + itarget.port_len,
+ itarget.path_len);
+ if (target->conf.http.path == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.http.path) != itarget.path_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+
+ if (itarget.auth_len) {
+ target->conf.http.auth = strndup(imsg->data +
+ sizeof(itarget) + itarget.hostname_len +
+ itarget.port_len + itarget.path_len,
+ itarget.auth_len);
+ if (target->conf.http.auth == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.http.auth) != itarget.auth_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ if (itarget.hmac_len) {
+ target->conf.http.hmac = strndup(imsg->data +
+ sizeof(itarget) + itarget.hostname_len +
+ itarget.port_len + itarget.path_len +
+ itarget.auth_len, itarget.hmac_len);
+ if (target->conf.http.hmac == NULL) {
+ err = got_error_from_errno("strndup");
+ goto done;
+ }
+ if (strlen(target->conf.http.hmac) != itarget.hmac_len) {
+ err = got_error(GOT_ERR_PRIVSEP_LEN);
+ goto done;
+ }
+ }
+
+ STAILQ_INSERT_TAIL(&gotd_session.notification_targets, target, entry);
+ target = NULL;
+done:
+ if (err)
+ free_notification_target(target);
+ return err;
+}
+
+static void
session_dispatch(int fd, short event, void *arg)
{
const struct got_error *err = NULL;
ssize_t n;
int shut = 0;
struct imsg imsg;
+ size_t npaths;
if (event & EV_READ) {
if ((n = imsgbuf_read(ibuf)) == -1)
break;
case GOTD_IMSG_DISCONNECT:
do_disconnect = 1;
+ break;
+ case GOTD_IMSG_NOTIFICATION_REFS:
+ if (gotd_session.notification_refs_cur != NULL ||
+ gotd_session.num_notification_refs_needed != 0) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ err = gotd_imsg_recv_pathlist(&npaths, &imsg);
+ if (err)
+ break;
+ gotd_session.notification_refs_cur =
+ &gotd_session.notification_refs;
+ gotd_session.num_notification_refs_needed = npaths;
+ gotd_session.num_notification_refs_received = 0;
+ break;
+ case GOTD_IMSG_NOTIFICATION_REF_NAMESPACES:
+ if (gotd_session.notification_refs_cur != NULL ||
+ gotd_session.num_notification_refs_needed != 0) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ err = gotd_imsg_recv_pathlist(&npaths, &imsg);
+ if (err)
+ break;
+ gotd_session.notification_refs_cur =
+ &gotd_session.notification_ref_namespaces;
+ gotd_session.num_notification_refs_needed = npaths;
+ gotd_session.num_notification_refs_received = 0;
break;
+ break;
+ case GOTD_IMSG_NOTIFICATION_REFS_ELEM:
+ case GOTD_IMSG_NOTIFICATION_REF_NAMESPACES_ELEM:
+ if (gotd_session.notification_refs_cur == NULL ||
+ gotd_session.num_notification_refs_needed == 0 ||
+ gotd_session.num_notification_refs_received >=
+ gotd_session.num_notification_refs_needed) {
+ err = got_error(GOT_ERR_PRIVSEP_MSG);
+ break;
+ }
+ err = gotd_imsg_recv_pathlist_elem(&imsg,
+ gotd_session.notification_refs_cur);
+ if (err)
+ break;
+ if (++gotd_session.num_notification_refs_received >=
+ gotd_session.num_notification_refs_needed) {
+ gotd_session.notification_refs_cur = NULL;
+ gotd_session.num_notification_refs_needed = 0;
+ }
+ break;
+ case GOTD_IMSG_NOTIFICATION_TARGET_EMAIL:
+ err = recv_notification_target_email(&imsg);
+ break;
+ case GOTD_IMSG_NOTIFICATION_TARGET_HTTP:
+ err = recv_notification_target_http(&imsg);
+ break;
case GOTD_IMSG_CONNECT_NOTIFIER:
err = recv_notifier(&imsg);
break;
void
session_write_main(const char *title, const char *repo_path,
- int *pack_fds, int *temp_fds, int content_fd,
- struct timeval *request_timeout, struct gotd_repo *repo_cfg)
+ int *pack_fds, int *temp_fds, int content_fd)
{
const struct got_error *err = NULL;
struct event evsigint, evsigterm, evsighup, evsigusr1;
gotd_session.pack_fds = pack_fds;
gotd_session.temp_fds = temp_fds;
gotd_session.content_fd = content_fd;
- memcpy(&gotd_session.request_timeout, request_timeout,
- sizeof(gotd_session.request_timeout));
- gotd_session.repo_cfg = repo_cfg;
+ gotd_session.request_timeout.tv_sec = GOTD_DEFAULT_REQUEST_TIMEOUT;
+ gotd_session.request_timeout.tv_usec = 0;
+ RB_INIT(&gotd_session.notification_refs);
+ RB_INIT(&gotd_session.notification_ref_namespaces);
+ STAILQ_INIT(&gotd_session.notification_targets);
if (imsgbuf_init(&gotd_session.notifier_iev.ibuf, -1) == -1) {
err = got_error_from_errno("imsgbuf_init");
blob - ee305618aa6d63a642f30434e275cd9891eef086
blob + d49eece585f1b9c8fb4214f0727c03bceda85676
--- gotd/session_write.h
+++ gotd/session_write.h
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-void session_write_main(const char *, const char *, int *, int *, int,
- struct timeval *, struct gotd_repo *);
+void session_write_main(const char *, const char *, int *, int *, int);