Added first files.
Signed-off-by: Tyrolyean <tyrolyean@tyrolyean.net>
This commit is contained in:
parent
7d2743229c
commit
70ca730f3d
2 changed files with 292 additions and 0 deletions
42
Makefile
Normal file
42
Makefile
Normal file
|
@ -0,0 +1,42 @@
|
|||
MKDIR_P := mkdir -p
|
||||
CP := cp
|
||||
MV := mv
|
||||
CC := gcc
|
||||
CCC := g++
|
||||
RM_RF = rm -rf
|
||||
|
||||
# directories
|
||||
CWD := $(realpath .)
|
||||
BINDIR := $(CWD)/bin
|
||||
BUILDDIR := $(CWD)/build
|
||||
SRCDIR := $(CWD)/src
|
||||
INCLUDEDIR := $(CWD)/include
|
||||
|
||||
# flas
|
||||
CFLAGS := -O2 -I$(INCLUDEDIR) -Wall -Wextra
|
||||
LDFLAGS := -pthread
|
||||
|
||||
# target files
|
||||
DIRS_TARGET := $(BINDIR) $(BUILDDIR)
|
||||
TARGET := $(BINDIR)/mailattach
|
||||
SRCFILES := $(wildcard $(SRCDIR)/*.c)
|
||||
OBJFILES := $(patsubst $(SRCDIR)/%.c,$(BUILDDIR)/%.o,$(SRCFILES))
|
||||
|
||||
# fancy targets
|
||||
all: directories $(TARGET)
|
||||
|
||||
directories: $(DIRS_TARGET)
|
||||
|
||||
# less fancy targets
|
||||
|
||||
$(DIRS_TARGET):
|
||||
$(MKDIR_P) $@
|
||||
|
||||
$(TARGET): $(OBJFILES)
|
||||
$(CC) $(LDFLAGS) -o $@ $^ /usr/lib/libmilter.a
|
||||
|
||||
$(BUILDDIR)/%.o: $(SRCDIR)/%.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM_RF) $(DIRS_TARGET)
|
250
src/main.c
Normal file
250
src/main.c
Normal file
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Mailattach - a program to remove attachments and replace them with links.
|
||||
* Licensed under the Apache 2.0 License. Parts taken from the sendmail
|
||||
* libmilter sample. License restrictions from their license may apply.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <libmilter/mfapi.h>
|
||||
#include <libmilter/mfdef.h>
|
||||
|
||||
|
||||
struct mlfiPriv
|
||||
{
|
||||
char *mlfi_fname;
|
||||
FILE *mlfi_fp;
|
||||
};
|
||||
|
||||
#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx))
|
||||
|
||||
static unsigned long mta_caps = 0;
|
||||
|
||||
sfsistat mlfi_cleanup(SMFICTX* ctx, bool ok) {
|
||||
sfsistat rstat = SMFIS_CONTINUE;
|
||||
struct mlfiPriv *priv = MLFIPRIV;
|
||||
char *p;
|
||||
char host[512];
|
||||
char hbuf[1024];
|
||||
|
||||
if (priv == NULL)
|
||||
return rstat;
|
||||
|
||||
/* close the archive file */
|
||||
if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF)
|
||||
{
|
||||
/* failed; we have to wait until later */
|
||||
rstat = SMFIS_TEMPFAIL;
|
||||
(void) unlink(priv->mlfi_fname);
|
||||
}
|
||||
else if (ok)
|
||||
{
|
||||
/* add a header to the message announcing our presence */
|
||||
if (gethostname(host, sizeof host) < 0){
|
||||
snprintf(host, sizeof host, "localhost");
|
||||
}
|
||||
p = strrchr(priv->mlfi_fname, '/');
|
||||
if (p == NULL)
|
||||
p = priv->mlfi_fname;
|
||||
else
|
||||
p++;
|
||||
snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
|
||||
smfi_addheader(ctx, "X-Archived", hbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* message was aborted -- delete the archive file */
|
||||
(void) unlink(priv->mlfi_fname);
|
||||
}
|
||||
|
||||
/* release private memory */
|
||||
free(priv->mlfi_fname);
|
||||
free(priv);
|
||||
smfi_setpriv(ctx, NULL);
|
||||
|
||||
/* return status */
|
||||
return rstat;
|
||||
}
|
||||
|
||||
|
||||
sfsistat
|
||||
mlfi_envfrom(ctx, envfrom)
|
||||
SMFICTX *ctx;
|
||||
char **envfrom;
|
||||
{
|
||||
struct mlfiPriv *priv;
|
||||
int fd = -1;
|
||||
|
||||
/* allocate some private memory */
|
||||
priv = malloc(sizeof *priv);
|
||||
if (priv == NULL)
|
||||
{
|
||||
/* can't accept this message right now */
|
||||
return SMFIS_TEMPFAIL;
|
||||
}
|
||||
memset(priv, '\0', sizeof *priv);
|
||||
|
||||
/* open a file to store this message */
|
||||
priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX");
|
||||
if (priv->mlfi_fname == NULL)
|
||||
{
|
||||
free(priv);
|
||||
return SMFIS_TEMPFAIL;
|
||||
}
|
||||
if ((fd = mkstemp(priv->mlfi_fname)) < 0 ||
|
||||
(priv->mlfi_fp = fdopen(fd, "w+")) == NULL)
|
||||
{
|
||||
if (fd >= 0)
|
||||
(void) close(fd);
|
||||
free(priv->mlfi_fname);
|
||||
free(priv);
|
||||
return SMFIS_TEMPFAIL;
|
||||
}
|
||||
|
||||
/* save the private data */
|
||||
smfi_setpriv(ctx, priv);
|
||||
|
||||
/* continue processing */
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat
|
||||
mlfi_header(ctx, headerf, headerv)
|
||||
SMFICTX *ctx;
|
||||
char *headerf;
|
||||
char *headerv;
|
||||
{
|
||||
/* write the header to the log file */
|
||||
fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv);
|
||||
|
||||
/* continue processing */
|
||||
return ((mta_caps & SMFIP_NR_HDR) != 0)
|
||||
? SMFIS_NOREPLY : SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat
|
||||
mlfi_eoh(ctx)
|
||||
SMFICTX *ctx;
|
||||
{
|
||||
/* output the blank line between the header and the body */
|
||||
fprintf(MLFIPRIV->mlfi_fp, "\r\n");
|
||||
|
||||
/* continue processing */
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat mlfi_body(SMFICTX* ctx, unsigned char * bodyp, size_t bodylen) {
|
||||
|
||||
/* output body block to log file */
|
||||
if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0)
|
||||
{
|
||||
/* write failed */
|
||||
(void) mlfi_cleanup(ctx, false);
|
||||
return SMFIS_TEMPFAIL;
|
||||
}
|
||||
|
||||
/* continue processing */
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat mlfi_eom(ctx)
|
||||
SMFICTX *ctx;
|
||||
{
|
||||
return mlfi_cleanup(ctx, true);
|
||||
}
|
||||
|
||||
sfsistat mlfi_close(ctx)
|
||||
SMFICTX *ctx;
|
||||
{
|
||||
return SMFIS_ACCEPT;
|
||||
}
|
||||
|
||||
sfsistat mlfi_abort(ctx)
|
||||
SMFICTX *ctx;
|
||||
{
|
||||
return mlfi_cleanup(ctx, false);
|
||||
}
|
||||
|
||||
sfsistat mlfi_unknown(ctx, cmd)
|
||||
SMFICTX *ctx;
|
||||
char *cmd;
|
||||
{
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat mlfi_data(ctx)
|
||||
SMFICTX *ctx;
|
||||
{
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
sfsistat
|
||||
mlfi_negotiate(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3)
|
||||
SMFICTX *ctx;
|
||||
unsigned long f0;
|
||||
unsigned long f1;
|
||||
unsigned long f2;
|
||||
unsigned long f3;
|
||||
unsigned long *pf0;
|
||||
unsigned long *pf1;
|
||||
unsigned long *pf2;
|
||||
unsigned long *pf3;
|
||||
{
|
||||
/* milter actions: add headers */
|
||||
*pf0 = SMFIF_ADDHDRS;
|
||||
|
||||
/* milter protocol steps: all but connect, HELO, RCPT */
|
||||
*pf1 = SMFIP_NOCONNECT|SMFIP_NOHELO|SMFIP_NORCPT;
|
||||
mta_caps = f1;
|
||||
if ((mta_caps & SMFIP_NR_HDR) != 0)
|
||||
*pf1 |= SMFIP_NR_HDR;
|
||||
*pf2 = 0;
|
||||
*pf3 = 0;
|
||||
return SMFIS_CONTINUE;
|
||||
}
|
||||
|
||||
struct smfiDesc smfilter =
|
||||
{
|
||||
"mailattach", /* filter name */
|
||||
SMFI_VERSION, /* version code -- do not change */
|
||||
SMFIF_ADDHDRS, /* flags */
|
||||
NULL, /* connection info filter */
|
||||
NULL, /* SMTP HELO command filter */
|
||||
mlfi_envfrom, /* envelope sender filter */
|
||||
NULL, /* envelope recipient filter */
|
||||
mlfi_header, /* header filter */
|
||||
mlfi_eoh, /* end of header */
|
||||
mlfi_body, /* body block filter */
|
||||
mlfi_eom, /* end of message */
|
||||
mlfi_abort, /* message aborted */
|
||||
mlfi_close, /* connection cleanup */
|
||||
mlfi_unknown, /* unknown/unimplemented SMTP commands */
|
||||
mlfi_data, /* DATA command filter */
|
||||
mlfi_negotiate /* option negotiation at connection startup */
|
||||
};
|
||||
|
||||
/* The actual entry point for the program. Performs initialisation routines and
|
||||
* then hands over to the libmilter main function */
|
||||
int main(){
|
||||
|
||||
const char* socket_location = "/var/run/mailattach";
|
||||
|
||||
|
||||
smfi_setconn("local:/var/run/mailattach");
|
||||
|
||||
if (smfi_register(smfilter) == MI_FAILURE)
|
||||
{
|
||||
fprintf(stderr, "smfi_register failed\n");
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
chmod(socket_location,0x1FF);
|
||||
return smfi_main();
|
||||
}
|
Loading…
Reference in a new issue