From: Omar Polo Subject: got-notify-email: spilt dial() out of send_email() To: gameoftrees@openbsd.org Date: Wed, 20 Mar 2024 11:43:37 +0100 By splitting out a dial() function from send_mail(), we can further reduce the pledge() in main down to "stdio". Other than being nice on its own, this also helps -portable, for e.g. on freebsd we could use capsicum(4). While here, do the usual loop around getaddrinfo() in case we fail to connect to the first result. ok? diff /home/op/w/got commit - dfa6ae4cb7d2e0474c8458b5622eca0385470c01 path + /home/op/w/got blob - d2e507fdfece9c9538bfe12b6cd820f899d7a552 file + gotd/libexec/got-notify-email/got-notify-email.c --- gotd/libexec/got-notify-email/got-notify-email.c +++ gotd/libexec/got-notify-email/got-notify-email.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,48 @@ usage(void) exit(1); } +static int +dial(const char *host, const char *port) +{ + struct addrinfo hints, *res, *res0; + const char *cause = NULL; + int s, error, save_errno; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(host, port, &hints, &res0); + if (error) + errx(1, "failed to resolve %s:%s: %s", host, port, + gai_strerror(error)); + + s = -1; + for (res = res0; res; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (s == -1) { + cause = "socket"; + continue; + } + + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) { + cause = "connect"; + save_errno = errno; + close(s); + errno = save_errno; + s = -1; + continue; + } + + break; + } + + freeaddrinfo(res0); + if (s == -1) + err(1, "%s", cause); + return s; +} + static char * set_default_fromaddr(void) { @@ -156,16 +199,14 @@ get_datestr(time_t *time, char *datebuf) } static void -send_email(const char *myfromaddr, const char *fromaddr, +send_email(int s, const char *myfromaddr, const char *fromaddr, const char *recipient, const char *replytoaddr, - const char *subject, const char *hostname, const char *port) + const char *subject) { const struct got_error *error; char *line = NULL; size_t linesize = 0; ssize_t linelen; - struct addrinfo hints, *res = NULL; - int s = -1, ret; time_t now; char datebuf[26]; char *datestr; @@ -173,21 +214,6 @@ send_email(const char *myfromaddr, const char *fromadd now = time(NULL); datestr = get_datestr(&now, datebuf); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - ret = getaddrinfo(hostname, port, &hints, &res); - if (ret) - errx(1, "getaddrinfo: %s", gai_strerror(ret)); - - s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s == -1) - err(1, "socket"); - - if (connect(s, res->ai_addr, res->ai_addrlen) == -1) - err(1, "connect %s:%s", hostname, port); - if (read_smtp_code(s, "220")) errx(1, "unexpected SMTP greeting received"); if (skip_to_crlf(s)) @@ -266,8 +292,6 @@ send_email(const char *myfromaddr, const char *fromadd close(s); free(line); - if (res) - freeaddrinfo(res); } int @@ -280,7 +304,7 @@ main(int argc, char *argv[]) const char *port = "25"; const char *errstr; char *timeoutstr; - int ch; + int ch, s; while ((ch = getopt(argc, argv, "f:r:s:h:p:")) != -1) { switch (ch) { @@ -336,9 +360,16 @@ main(int argc, char *argv[]) if (fromaddr == NULL) fromaddr = default_fromaddr; - send_email(default_fromaddr, fromaddr, recipient, replytoaddr, - subject, hostname, port); + s = dial(hostname, port); +#ifndef PROFILE + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +#endif + + send_email(s, default_fromaddr, fromaddr, recipient, replytoaddr, + subject); + free(default_fromaddr); return 0; }