pop3

Tiny pop3 client designed to be tunneled through ssh
git clone git://jacobedwards.org/pop3
Log | Files | Refs

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:
Mpop3.1 | 6+++++-
Mpop3.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); }