/*
- * slocal.c -- asynchronously filter and deliver new mail
- *
- * This code is Copyright (c) 2002, by the authors of nmh. See the
- * COPYRIGHT file in the root directory of the nmh distribution for
- * complete copyright information.
- */
+** slocal.c -- asynchronously filter and deliver new mail
+**
+** This code is Copyright (c) 2002, by the authors of nmh. See the
+** COPYRIGHT file in the root directory of the nmh distribution for
+** complete copyright information.
+*/
/*
- * Under sendmail, users should add the line
- *
- * "| /usr/local/nmh/lib/slocal"
- *
- * to their $HOME/.forward file.
- *
- */
+** Under sendmail, users should add the line
+**
+** "| /usr/local/nmh/lib/slocal"
+**
+** to their $HOME/.forward file.
+**
+*/
/* Changed to use getutent() and friends. Assumes that when getutent() exists,
- * a number of other things also exist. Please check.
- * Ruud de Rooij <ruud@ruud.org> Sun, 28 May 2000 17:28:55 +0200
- */
+** a number of other things also exist. Please check.
+** Ruud de Rooij <ruud@ruud.org> Sun, 28 May 2000 17:28:55 +0200
+*/
#include <h/mh.h>
#include <h/dropsbr.h>
#ifdef INITGROUPS_HEADER
#include INITGROUPS_HEADER
#else
-/* On AIX 4.1, initgroups() is defined and even documented (giving the parameter
- types as char* and int), but doesn't have a prototype in any of the system
- header files. AIX 4.3, SunOS 4.1.3, and ULTRIX 4.2A have the same
- problem. */
+/*
+** On AIX 4.1, initgroups() is defined and even documented (giving the
+** parameter types as char* and int), but doesn't have a prototype in any
+** of the system header files. AIX 4.3, SunOS 4.1.3, and ULTRIX 4.2A have
+** the same problem.
+*/
extern int initgroups(char*, int);
#endif
-/* This define is needed for Berkeley db v2 and above to
- * make the header file expose the 'historical' ndbm APIs.
- * We define it unconditionally because this is simple and
- * harmless.
- */
+/*
+** This define is needed for Berkeley db v2 and above to
+** make the header file expose the 'historical' ndbm APIs.
+** We define it unconditionally because this is simple and
+** harmless.
+*/
#define DB_DBM_HSEARCH 1
#ifdef NDBM_HEADER
#include NDBM_HEADER
#define NVEC 100
/*
- * Lookup table for matching fields and patterns
- * in messages. The rest of the table is added
- * when the message is parsed.
- */
+** Lookup table for matching fields and patterns
+** in messages. The rest of the table is added
+** when the message is parsed.
+*/
static struct pair hdrs[NVEC + 1] = {
{ "source", NULL, P_HID },
{ "addr", NULL, P_HID },
};
/*
- * The list of builtin variables to expand in a string
- * before it is executed by the "pipe" or "qpipe" action.
- */
+** The list of builtin variables to expand in a string
+** before it is executed by the "pipe" or "qpipe" action.
+*/
static struct pair vars[] = {
{ "sender", NULL, P_NIL },
{ "address", NULL, P_NIL },
extern char **environ;
/*
- * static prototypes
- */
+** static prototypes
+*/
static int localmail (int, char *);
static int usr_delivery (int, char *, int);
static int split (char *, char **);
done (1);
case ADDRSW:
- if (!(addr = *argp++))/* allow -xyz arguments */
+ if (!(addr = *argp++))
+ /* allow -xyz arguments */
adios (NULL, "missing argument to %s", argp[-2]);
continue;
case INFOSW:
- if (!(info = *argp++))/* allow -xyz arguments */
+ if (!(info = *argp++))
+ /* allow -xyz arguments */
adios (NULL, "missing argument to %s", argp[-2]);
continue;
case USERSW:
- if (!(user = *argp++))/* allow -xyz arguments */
+ if (!(user = *argp++))
+ /* allow -xyz arguments */
adios (NULL, "missing argument to %s", argp[-2]);
continue;
case FILESW:
adios (NULL, "missing argument to %s", argp[-2]);
continue;
case SENDERSW:
- if (!(sender = *argp++))/* allow -xyz arguments */
+ if (!(sender = *argp++))
+ /* allow -xyz arguments */
adios (NULL, "missing argument to %s", argp[-2]);
continue;
case MAILBOXSW:
snprintf (ddate, sizeof(ddate), "Delivery-Date: %s\n", dtimenow (0));
/*
- * Copy the message to a temporary file
- */
+ ** Copy the message to a temporary file
+ */
if (file) {
int tempfd;
debug_printf ("temporary file=\"%s\"\n", tmpfil);
/*
- * Delete the temp file now or a copy of every single message
- * passed through slocal will be left in the /tmp directory until
- * deleted manually! This unlink() used to be under an 'else'
- * of the 'if (debug)' above, but since some people like to
- * always run slocal with -debug and log the results, the /tmp
- * directory would get choked over time. Of course, now that
- * we always delete the temp file, the "temporary file=" message
- * above is somewhat pointless -- someone watching debug output
- * wouldn't have a chance to 'tail -f' or 'ln' the temp file
- * before it's unlinked. The best thing would be to delay this
- * unlink() until later if debug == 1, but I'll leave that for
- * someone who cares about the temp-file-accessing functionality
- * (they'll have to watch out for cases where we adios()).
- */
+ ** Delete the temp file now or a copy of every single message
+ ** passed through slocal will be left in the /tmp directory until
+ ** deleted manually! This unlink() used to be under an 'else'
+ ** of the 'if (debug)' above, but since some people like to
+ ** always run slocal with -debug and log the results, the /tmp
+ ** directory would get choked over time. Of course, now that
+ ** we always delete the temp file, the "temporary file=" message
+ ** above is somewhat pointless -- someone watching debug output
+ ** wouldn't have a chance to 'tail -f' or 'ln' the temp file
+ ** before it's unlinked. The best thing would be to delay this
+ ** unlink() until later if debug == 1, but I'll leave that for
+ ** someone who cares about the temp-file-accessing functionality
+ ** (they'll have to watch out for cases where we adios()).
+ */
unlink (tmpfil);
if (!(fp = fdopen (fd, "r+")))
adios (NULL, "unable to access temporary file");
/*
- * If no sender given, extract it
- * from envelope information. */
+ ** If no sender given, extract it
+ ** from envelope information.
+ */
if (sender == NULL)
get_sender (envelope, &sender);
debug_printf ("user=\"%s\"\n", trim(user));
debug_printf ("info=\"%s\"\n", trim(info));
debug_printf ("sender=\"%s\"\n", trim(sender));
- debug_printf ("envelope=\"%s\"\n", envelope ? trim(envelope) : "");
+ debug_printf ("envelope=\"%s\"\n",
+ envelope ? trim(envelope) : "");
debug_printf ("mbox=\"%s\"\n", trim(mbox));
debug_printf ("home=\"%s\"\n", trim(home));
debug_printf ("ddate=\"%s\"\n", trim(ddate));
/*
- * Main routine for delivering message.
- */
+** Main routine for delivering message.
+*/
static int
localmail (int fd, char *mdlvr)
{
/* check if this message is a duplicate */
if (suppressdup &&
- suppress_duplicates(fd, mdlvr ? mdlvr : ".maildelivery") == DONE)
+ suppress_duplicates(fd,
+ mdlvr ? mdlvr : ".maildelivery") == DONE)
return 0;
/* delivery according to personal Maildelivery file */
#define matches(a,b) (stringdex (b, a) >= 0)
/*
- * Parse the delivery file, and process incoming message.
- */
+** Parse the delivery file, and process incoming message.
+*/
static int
usr_delivery (int fd, char *delivery, int su)
|| (st.st_uid != 0 && (su || st.st_uid != pw->pw_uid))
|| st.st_mode & (S_IWGRP|S_IWOTH)) {
if (verbose) {
- verbose_printf ("WARNING: %s has bad ownership/modes (su=%d,uid=%d,owner=%d,mode=0%o)\n",
- delivery, su, (int) pw->pw_uid, (int) st.st_uid, (int) st.st_mode);
+ verbose_printf ("WARNING: %s has bad ownership/modes (su=%d,uid=%d,owner=%d,mode=0%o)\n", delivery, su, (int) pw->pw_uid, (int) st.st_uid, (int) st.st_mode);
}
return -1;
}
if (debug) {
for (i = 0; vec[i]; i++)
- debug_printf ("vec[%d]: \"%s\"\n", i, trim(vec[i]));
+ debug_printf ("vec[%d]: \"%s\"\n",
+ i, trim(vec[i]));
}
field = vec[0];
case 'N':
case 'n':
/*
- * If previous condition failed, don't
- * do this - else fall through
- */
+ ** If previous condition failed, don't
+ ** do this - else fall through
+ */
if (!next)
continue; /* else fall */
case '?':
/*
- * If already delivered, skip this action. Else
- * consider delivered if action is successful.
- */
+ ** If already delivered, skip this action.
+ ** Else consider delivered if action is
+ ** successful.
+ */
if (won)
continue; /* else fall */
case 'A':
case 'a':
/*
- * Take action, and consider delivered if
- * action is successful.
- */
+ ** Take action, and consider delivered if
+ ** action is successful.
+ */
accept = 1;
break;
case 'r':
default:
/*
- * Take action, but don't consider delivered, even
- * if action is successful
- */
+ ** Take action, but don't consider delivered,
+ ** even if action is successful
+ */
accept = 0;
break;
}
case 'd':
/*
- * "default" matches only if the message hasn't
- * been delivered yet.
- */
+ ** "default" matches only if the message hasn't
+ ** been delivered yet.
+ */
if (!mh_strcasecmp (field, "default")) {
if (won)
continue;
return -1;
}
/*
- * find header field in lookup table, and
- * see if the pattern matches.
- */
- if ((p = lookup (hdrs, field)) && (p->p_value != NULL)
- && matches (p->p_value, pattern)) {
+ ** find header field in lookup table, and
+ ** see if the pattern matches.
+ */
+ if ((p = lookup (hdrs, field)) &&
+ (p->p_value != NULL) &&
+ matches (p->p_value, pattern)
+ ) {
next = 1;
} else {
next = 0;
expand (tmpbuf, string, fd);
vec[4] = tmpbuf;
vec[5] = NULL;
- status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2, 0);
+ status = usr_pipe (fd, tmpbuf, "/bin/sh",
+ vec + 2, 0);
break;
case 'f':
/* mbox format */
if (!mh_strcasecmp (action, "file")) {
- status = usr_file (fd, string, MBOX_FORMAT);
+ status = usr_file (fd, string,
+ MBOX_FORMAT);
break;
}
/* deliver to nmh folder */
case 'm':
/* mmdf format */
if (!mh_strcasecmp (action, "mmdf")) {
- status = usr_file (fd, string, MMDF_FORMAT);
+ status = usr_file (fd, string,
+ MMDF_FORMAT);
break;
}
/* mbox format */
#define QUOTE '\\'
/*
- * Split buffer into fields (delimited by whitespace or
- * comma's). Return the number of fields found.
- */
+** Split buffer into fields (delimited by whitespace or
+** comma's). Return the number of fields found.
+*/
static int
split (char *cp, char **vec)
if (*s == '"') {
for (vec[i++] = ++s; *s && *s != '"'; s++) {
/*
- * Check for escaped double quote. We need
- * to shift the string to remove slash.
- */
+ ** Check for escaped double quote. We need
+ ** to shift the string to remove slash.
+ */
if (*s == QUOTE) {
if (*++s == '"')
strcpy (s - 1, s);
/*
- * Parse the headers of a message, and build the
- * lookup table for matching fields and patterns.
- */
+** Parse the headers of a message, and build the
+** lookup table for matching fields and patterns.
+*/
static int
parse (int fd)
* a lookup table.
*/
for (i = 0, state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), in)) {
+ switch (state = m_getfld (state, name, field, sizeof(field),
+ in)) {
case FLD:
case FLDEOF:
case FLDPLUS:
#define RPAREN ')'
/*
- * Expand any builtin variables such as $(sender),
- * $(address), etc., in a string.
- */
+** Expand any builtin variables such as $(sender),
+** $(address), etc., in a string.
+*/
static void
expand (char *s1, char *s2, int fd)
/*
- * Fill in the information missing from the "vars"
- * table, which is necessary to expand any builtin
- * variables in the string for a "pipe" or "qpipe"
- * action.
- */
+** Fill in the information missing from the "vars"
+** table, which is necessary to expand any builtin
+** variables in the string for a "pipe" or "qpipe"
+** action.
+*/
static void
glob (int fd)
/*
- * Find a matching name in a lookup table. If found,
- * return the "pairs" entry, else return NULL.
- */
+** Find a matching name in a lookup table. If found,
+** return the "pairs" entry, else return NULL.
+*/
static struct pair *
lookup (struct pair *pairs, char *key)
/*
- * Check utmp(x) file to see if user is currently
- * logged in.
- */
+** Check utmp(x) file to see if user is currently
+** logged in.
+*/
#ifdef HAVE_GETUTENT
static int
while ((utp = getutent()) != NULL) {
if (
#ifdef HAVE_STRUCT_UTMP_UT_TYPE
- utp->ut_type == USER_PROCESS
- &&
+ utp->ut_type == USER_PROCESS &&
#endif
- utp->ut_name[0] != 0
- && strncmp (user, utp->ut_name, sizeof(utp->ut_name)) == 0) {
+ utp->ut_name[0] != 0 &&
+ strncmp (user, utp->ut_name,
+ sizeof(utp->ut_name)) == 0) {
if (debug)
continue;
endutent();
return NOTOK;
while (fread ((char *) &ut, sizeof(ut), 1, uf) == 1) {
- if (ut.ut_name[0] != 0
- && strncmp (user, ut.ut_name, sizeof(ut.ut_name)) == 0) {
+ if (ut.ut_name[0] != 0 &&
+ strncmp (user, ut.ut_name, sizeof(ut.ut_name))
+ == 0) {
if (debug)
continue;
fclose (uf);
/*
- * Deliver message by appending to a file.
- */
+** Deliver message by appending to a file.
+*/
static int
usr_file (int fd, char *mailbox, int mbx_style)
}
/* open and lock the file */
- if ((md = mbx_open (mailbox, mbx_style, pw->pw_uid, pw->pw_gid, m_gmprot())) == -1) {
+ if ((md = mbx_open (mailbox, mbx_style, pw->pw_uid, pw->pw_gid,
+ m_gmprot())) == -1) {
if (verbose)
adorn ("", "unable to open:");
return -1;
lseek (fd, (off_t) 0, SEEK_SET);
/* append message to file */
- if (mbx_copy (mailbox, mbx_style, md, fd, mapping, NULL, verbose) == -1) {
+ if (mbx_copy (mailbox, mbx_style, md, fd, mapping, NULL, verbose)
+ == -1) {
if (verbose)
adorn ("", "error writing to:");
return -1;
/*
- * Deliver message to a nmh folder.
- */
+** Deliver message to a nmh folder.
+*/
static int
usr_folder (int fd, char *string)
#if 0
/*
- * Currently, verbose status messages are handled by usr_pipe().
- */
+ ** Currently, verbose status messages are handled by usr_pipe().
+ */
if (verbose) {
if (status == 0)
verbose_printf (", success.\n");
}
/*
- * Deliver message to a process.
- */
+** Deliver message to a process.
+*/
static int
usr_pipe (int fd, char *cmd, char *pgm, char **vec, int suppress)
}
#endif /* TIOCNOTTY */
- setpgid ((pid_t) 0, getpid ()); /* put in own process group */
+ /* put in own process group */
+ setpgid ((pid_t) 0, getpid ());
*environ = NULL;
m_putenv ("USER", pw->pw_name);
/* parent process */
if (!setjmp (myctx)) {
SIGNAL (SIGALRM, alrmser);
- bytes = fstat (fd, &st) != -1 ? (int) st.st_size : 100;
+ bytes = fstat (fd, &st) != -1 ?
+ (int) st.st_size : 100;
- /* amount of time to wait depends on message size */
+ /*
+ ** amount of time to wait depends on
+ ** message size
+ */
if (bytes <= 100) {
/* give at least 5 minutes */
seconds = 300;
return (status == 0 ? 0 : -1);
} else {
/*
- * Ruthlessly kill the child and anything
- * else in its process group.
- */
+ ** Ruthlessly kill the child and anything
+ ** else in its process group.
+ */
KILLPG(child_id, SIGKILL);
if (verbose)
verbose_printf (", timed-out; terminated\n");
/*
- * Get the `sender' from the envelope
- * information ("From " line).
- */
+** Get the `sender' from the envelope
+** information ("From " line).
+*/
static void
get_sender (char *envelope, char **sender)
/*
- * Copy message into a temporary file.
- * While copying, it will do some header processing
- * including the extraction of the envelope information.
- */
+** Copy message into a temporary file.
+** While copying, it will do some header processing
+** including the extraction of the envelope information.
+*/
static int
copy_message (int qd, char *tmpfil, int fold)
}
/*
- * copy message into temporary file
- * and massage the headers. Save
- * a copy of the "From " line for later.
- */
+ ** copy message into temporary file
+ ** and massage the headers. Save
+ ** a copy of the "From " line for later.
+ */
i = strlen ("From ");
while (fgets (buffer, sizeof(buffer), qfp)) {
if (first) {
#ifdef RPATHS
char *fp, *cp, *hp, *ep;
#endif
- /* get copy of envelope information ("From " line) */
+ /*
+ ** get copy of envelope information
+ ** ("From " line)
+ */
envelope = getcpy (buffer);
#if 0
- /* First go ahead and put "From " line in message */
+ /*
+ ** First go ahead and put "From " line
+ ** in message
+ */
fputs (buffer, ffp);
if (ferror (ffp))
goto fputs_error;
#ifdef RPATHS
/*
- * Now create a "Return-Path:" line
- * from the "From " line.
- */
+ ** Now create a "Return-Path:" line
+ ** from the "From " line.
+ */
hp = cp = strchr(fp = envelope + i, ' ');
while ((hp = strchr(++hp, 'r')))
if (uprf (hp, "remote from")) {
break;
}
if (hp) {
- /* return path for UUCP style addressing */
+ /*
+ ** return path for UUCP style
+ ** addressing
+ */
ep = strchr(++hp, '\n');
- snprintf (buffer, sizeof(buffer), "Return-Path: %.*s!%.*s\n",
- (int)(ep - hp), hp, (int)(cp - fp), fp);
+ snprintf (buffer, sizeof(buffer), "Return-Path: %.*s!%.*s\n", (int)(ep - hp), hp, (int)(cp - fp), fp);
} else {
- /* return path for standard domain addressing */
- snprintf (buffer, sizeof(buffer), "Return-Path: %.*s\n",
- (int)(cp - fp), fp);
+ /*
+ ** return path for standard domain
+ ** addressing
+ */
+ snprintf (buffer, sizeof(buffer), "Return-Path: %.*s\n", (int)(cp - fp), fp);
}
/* Add Return-Path header to message */
}
/*
- * Trim strings for pretty printing of debugging output
- */
+** Trim strings for pretty printing of debugging output
+*/
static char *
trim (char *cp)
}
/*
- * Function for printing `verbose' messages.
- */
+** Function for printing `verbose' messages.
+*/
static void
verbose_printf (char *fmt, ...)
/*
- * Function for printing `verbose' delivery
- * error messages.
- */
+** Function for printing `verbose' delivery
+** error messages.
+*/
static void
adorn (char *what, char *fmt, ...)
/*
- * Function for printing `debug' messages.
- */
+** Function for printing `debug' messages.
+*/
static void
debug_printf (char *fmt, ...)
/*
- * Check ndbm/db file(s) to see if the Message-Id of this
- * message matches the Message-Id of a previous message,
- * so we can discard it. If it doesn't match, we add the
- * Message-Id of this message to the ndbm/db file.
- */
+** Check ndbm/db file(s) to see if the Message-Id of this
+** message matches the Message-Id of a previous message,
+** so we can discard it. If it doesn't match, we add the
+** Message-Id of this message to the ndbm/db file.
+*/
static int
suppress_duplicates (int fd, char *file)
{
return -1;
}
/*
- * Since it is difficult to portable
- * lock a ndbm file, we will open and
- * lock the Maildelivery file instead.
- * This will fail if your Maildelivery
- * file doesn't exist.
- */
+ ** Since it is difficult to portable
+ ** lock a ndbm file, we will open and
+ ** lock the Maildelivery file instead.
+ ** This will fail if your Maildelivery
+ ** file doesn't exist.
+ */
if ((lockfd = lkopen(file, O_RDWR, 0)) == -1) {
advise (file, "unable to perform file locking on");
free (cp);
value = dbm_fetch (db, key);
if (value.dptr) {
if (verbose)
- verbose_printf ("Message-ID: %s\n already received on %s",
- cp, value.dptr);
+ verbose_printf ("Message-ID: %s\n already received on %s", cp, value.dptr);
result = DONE;
} else {
value.dptr = ddate + sizeof("Delivery-Date:");