commit a994c1755a6f17171db0bd9a56efd28f03954949 from: Stefan Sperling date: Mon Mar 11 09:49:09 2024 UTC run email notification helper commit - 3c347461535dd1482d9f22df0ede0f245c092180 commit + a994c1755a6f17171db0bd9a56efd28f03954949 blob - 532bc19306dddc32e7c2236a2b958a02e9c0bf8b blob + 020795e6496b2f22da447417c67793d1b001f5f6 --- gotd/gotd.c +++ gotd/gotd.c @@ -1983,6 +1983,8 @@ main(int argc, char **argv) struct event evsigint, evsigterm, evsighup, evsigusr1, evsigchld; int *pack_fds = NULL, *temp_fds = NULL; struct gotd_repo *repo = NULL; + char *default_sender = NULL; + char hostname[HOST_NAME_MAX + 1]; TAILQ_INIT(&procs); @@ -2109,6 +2111,11 @@ main(int argc, char **argv) } else if (proc_id == PROC_NOTIFY) { snprintf(title, sizeof(title), "%s %s", gotd_proc_names[proc_id], repo_path); + if (gethostname(hostname, sizeof(hostname)) == -1) + fatal("gethostname"); + if (asprintf(&default_sender, "%s@%s", + pw->pw_name, hostname) == -1) + fatal("asprintf"); } else fatal("invalid process id %d", proc_id); @@ -2217,7 +2224,7 @@ main(int argc, char **argv) */ unveil_notification_helpers(); - notify_main(title); + notify_main(title, &gotd.repos, default_sender); /* NOTREACHED */ exit(0); default: @@ -2252,6 +2259,7 @@ main(int argc, char **argv) event_dispatch(); free(repo_path); + free(default_sender); gotd_shutdown(); return 0; blob - 536e8f08bcba8d30704aa3b6ee94d5a1bb340368 blob + dcc070cb7fdab140e8aa219b04f1423c773bd7b0 --- gotd/gotd.h +++ gotd/gotd.h @@ -497,6 +497,12 @@ struct gotd_imsg_auth { gid_t egid; int required_auth; uint32_t client_id; +}; + +/* Structure for GOTD_IMSG_NOTIFY. */ +struct gotd_imsg_notify { + char repo_name[NAME_MAX]; + char subject_line[64]; }; int parse_config(const char *, enum gotd_procid, struct gotd *); blob - 78359bad4c5f1afe2fbc0dbf0c5a37663f8056b8 blob + bbb8bc71084a768db3ea5cabaf3053203b4ccfcc --- gotd/notify.c +++ gotd/notify.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include #include @@ -41,6 +43,8 @@ static struct gotd_notify { pid_t pid; const char *title; struct gotd_imsgev parent_iev; + struct gotd_repolist *repos; + const char *default_sender; } gotd_notify; void gotd_notify_sighdlr(int sig, short event, void *arg); @@ -72,6 +76,135 @@ gotd_notify_sighdlr(int sig, short event, void *arg) } static void +run_notification_helper(const char *prog, const char **argv, int fd) +{ + const struct got_error *err = NULL; + pid_t pid; + int child_status; + + pid = fork(); + if (pid == -1) { + err = got_error_from_errno("fork"); + log_warn("%s", err->msg); + return; + } else if (pid == 0) { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + if (dup2(fd, STDIN_FILENO) == -1) { + fprintf(stderr, "%s: dup2: %s\n", getprogname(), + strerror(errno)); + _exit(1); + } + + closefrom(STDERR_FILENO + 1); + + if (execv(prog, (char *const *)argv) == -1) { + fprintf(stderr, "%s: exec %s: %s\n", getprogname(), + prog, strerror(errno)); + _exit(1); + } + + /* not reached */ + } + + if (waitpid(pid, &child_status, 0) == -1) { + err = got_error_from_errno("waitpid"); + goto done; + } + + if (!WIFEXITED(child_status)) { + err = got_error(GOT_ERR_PRIVSEP_DIED); + goto done; + } + + if (WEXITSTATUS(child_status) != 0) + err = got_error(GOT_ERR_PRIVSEP_EXIT); +done: + if (err) + log_warnx("%s: child %s pid %d: %s", gotd_notify.title, + prog, pid, err->msg); +} + +static void +notify_email(struct gotd_notification_target *target, const char *subject_line, + int fd) +{ + const char *argv[9]; + int i = 0; + + argv[i++] = GOTD_PATH_PROG_NOTIFY_EMAIL; + + argv[i++] = "-f"; + if (target->conf.email.sender) + argv[i++] = target->conf.email.sender; + else + argv[i++] = gotd_notify.default_sender; + + if (target->conf.email.responder) { + argv[i++] = "-r"; + argv[i++] = target->conf.email.responder; + } + + argv[i++] = "-s"; + argv[i++] = subject_line; + + argv[i++] = target->conf.email.recipient; + + argv[i] = NULL; + + run_notification_helper(GOTD_PATH_PROG_NOTIFY_EMAIL, argv, fd); +} + +static void +notify_http(struct gotd_notification_target *target, const char *subject_line, + int fd) +{ + const char *argv[10] = { 0 }; /* TODO */ + + run_notification_helper(GOTD_PATH_PROG_NOTIFY_HTTP, argv, fd); +} + +static const struct got_error * +send_notifications(struct imsg *imsg) +{ + struct gotd_imsg_notify inotify; + size_t datalen; + struct gotd_repo *repo; + struct gotd_notification_target *target; + + datalen = imsg->hdr.len - IMSG_HEADER_SIZE; + if (datalen != sizeof(inotify)) + return got_error(GOT_ERR_PRIVSEP_LEN); + + memcpy(&inotify, imsg->data, datalen); + + if (imsg->fd == -1) + return got_error(GOT_ERR_PRIVSEP_NO_FD); + + TAILQ_FOREACH(repo, gotd_notify.repos, entry) { + if (strcmp(repo->name, inotify.repo_name) == 0) + break; + } + if (repo == NULL) + return got_error(GOT_ERR_PRIVSEP_MSG); + + STAILQ_FOREACH(target, &repo->notification_targets, entry) { + switch (target->type) { + case GOTD_NOTIFICATION_VIA_EMAIL: + notify_email(target, inotify.subject_line, imsg->fd); + break; + case GOTD_NOTIFICATION_VIA_HTTP: + notify_http(target, inotify.subject_line, imsg->fd); + break; + } + } + + return NULL; +} + +static void notify_dispatch(int fd, short event, void *arg) { struct gotd_imsgev *iev = arg; @@ -110,6 +243,10 @@ notify_dispatch(int fd, short event, void *arg) break; switch (imsg.hdr.type) { + case GOTD_IMSG_NOTIFY: + err = send_notifications(&imsg); + if (err) + break; default: log_debug("unexpected imsg %d", imsg.hdr.type); break; @@ -131,12 +268,15 @@ done: } void -notify_main(const char *title) +notify_main(const char *title, struct gotd_repolist *repos, + const char *default_sender) { const struct got_error *err = NULL; struct event evsigint, evsigterm, evsighup, evsigusr1; gotd_notify.title = title; + gotd_notify.repos = repos; + gotd_notify.default_sender = default_sender; gotd_notify.pid = getpid(); signal_set(&evsigint, SIGINT, gotd_notify_sighdlr, NULL); blob - 5ba452e52c2a67baf8c8220364b01201f02427a0 blob + 8772e7f321719d0df0848da2b7d3155f44379173 --- gotd/notify.h +++ gotd/notify.h @@ -14,4 +14,4 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -void notify_main(const char *); +void notify_main(const char *, struct gotd_repolist *, const char *);