commit 57d78289bb609835e7da65d1b001ea80603949ef
parent 1aa4eae25df8f50e7fff71c0801c1ae17eacb84e
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date: Sun, 3 Apr 2022 17:37:27 +0000
Add mailer option
This option pipes each message through the given program instead
of printing them to the standard output.
Diffstat:
M | pop3.1 | | | 6 | +++++- |
M | pop3.c | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- |
2 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/pop3.1 b/pop3.1
@@ -1,4 +1,4 @@
-.\" $Id: pop3.1,v 1.2 2022/03/25 22:54:19 jacob Exp $
+.\" $Id: pop3.1,v 1.3 2022/04/03 17:37:27 jacob Exp $
.\"
.\" Copyright (c) 2022 Jacob R. Edwards
.\"
@@ -23,6 +23,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl kqst
+.Op Fl m Ar mailer
.Op Fl p Ar port
.Op Fl u Ar user
.Ar host
@@ -53,6 +54,9 @@ by default
is used.
.It Fl t
Trace POP3 communication.
+.It Fl m Ar mailer
+Pipe each message through
+.Ar mailer .
.It Fl p Ar port
Connect to
.Ar host
diff --git a/pop3.c b/pop3.c
@@ -1,4 +1,4 @@
-/* $Id: pop3.c,v 1.1 2022/03/07 07:42:39 jacob Exp $ */
+/* $Id: pop3.c,v 1.2 2022/04/03 17:37:27 jacob Exp $ */
/*
* Copyright (c) 2022 Jacob R. Edwards
@@ -21,6 +21,7 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <netdb.h>
@@ -29,6 +30,7 @@
#include <libgen.h>
#include <limits.h>
#include <readpassphrase.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -56,6 +58,7 @@ static int trace;
static char *port = "110";
static char *user;
static char *host;
+static char *mailer;
struct scanlisting {
char msg[4 + 1]; /* See LISTMAX */
@@ -88,7 +91,7 @@ usage(char *why)
{
if (why)
fprintf(stderr, "%s\n", why);
- fprintf(stderr, "usage: %s [-kqst] [-u user] [-p port] host\n",
+ fprintf(stderr, "usage: %s [-kqst] [-m mailer] [-p port] [-u user] host\n",
getprogname());
exit(1);
}
@@ -387,17 +390,64 @@ pop_dele(FILE *fp, char *msg)
}
int
-mbox(FILE *fp, int delete)
+mail(FILE *fp, char *msg, char *mailer)
+{
+ int fds[2];
+ int status;
+ pid_t pid;
+
+ if (pipe(fds))
+ return -1;
+
+ switch ((pid = fork())) {
+ case -1:
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ case 0:
+ if (close(fds[1]) < 0 || dup2(fds[0], 0) < 0)
+ _exit(127);
+ execlp(mailer, mailer, NULL);
+ _exit(127);
+ }
+
+ if (close(fds[0]) < 0 || dup2(fds[1], 1) < 0 ||
+ pop_retr(fp, msg) || fflush(stdout)) {
+ close(fds[1]);
+ kill(pid, SIGTERM);
+ return -1;
+ }
+
+ if (close(fds[1]) < 0 || close(1) < 0) {
+ kill(pid, SIGTERM);
+ return -1;
+ }
+
+ if (waitpid(pid, &status, 0) < 0)
+ return -1;
+ return WEXITSTATUS(status);
+}
+
+int
+mbox(FILE *fp, char *msg, char *unused)
+{
+ return pop_retr(fp, msg);
+}
+
+int
+getmail(FILE *fp, int delete, char *mailer)
{
int len, i;
struct scanlisting *listings;
+ int (*sendmail)(FILE *, char *, char *);
listings = pop_list(fp, &len);
if (listings == NULL)
return 1;
+ sendmail = mailer ? mail : mbox;
for (i = 0; i < len; ++i) {
- if (pop_retr(fp, listings[i].msg) ||
+ if (sendmail(fp, listings[i].msg, mailer) ||
(delete && pop_dele(fp, listings[i].msg))) {
free(listings);
return 1;
@@ -440,15 +490,18 @@ main(int argc, char *argv[])
FILE *fp;
int c;
- if (pledge("stdio tty inet dns", NULL))
+ if (pledge("stdio tty inet dns proc exec", NULL))
die("pledge");
user = getlogin();
- while ((c = getopt(argc, argv, "kp:qstu:")) >= 0) {
+ while ((c = getopt(argc, argv, "km:p:qstu:")) >= 0) {
switch (c) {
case 'k':
keep = 1;
break;
+ case 'm':
+ mailer = optarg;
+ break;
case 'p':
port = optarg;
break;
@@ -484,10 +537,10 @@ main(int argc, char *argv[])
if (auth(fp, user, usestdin))
die("unable to authenticate for '%s'", user);
- if (pledge("stdio", NULL))
+ if (pledge(mailer ? "stdio proc exec" : "stdio", NULL))
die("pledge");
- if (query ? stat(fp) : mbox(fp, !keep))
+ if (query ? stat(fp) : getmail(fp, !keep, mailer))
die("unable to complete transaction");
return !pop_quit(fp);
}