-
-/*
- * slocal.c -- asynchronously filter and deliver new mail
+/* 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
* Ruud de Rooij <ruud@ruud.org> Sun, 28 May 2000 17:28:55 +0200
*/
-#include <h/mh.h>
-#include <h/dropsbr.h>
-#include <h/rcvmail.h>
-#include <h/signals.h>
+#include "h/mh.h"
+#include "sbr/ambigsw.h"
+#include "sbr/pidstatus.h"
+#include "sbr/print_version.h"
+#include "sbr/print_help.h"
+#include "sbr/error.h"
+#include "h/dropsbr.h"
+#include "h/rcvmail.h"
+#include "h/signals.h"
#include <setjmp.h>
-#include <h/tws.h>
-#include <h/mts.h>
-#include <h/utils.h>
+#include "h/tws.h"
+#include "h/mts.h"
+#include "h/done.h"
+#include "h/utils.h"
+#include "sbr/lock_file.h"
+#include "sbr/m_mktemp.h"
#include <pwd.h>
#include <sys/ioctl.h>
static int globbed = 0; /* have we built "vars" table yet? */
static int parsed = 0; /* have we built header field table yet */
static int utmped = 0; /* have we scanned umtp(x) file yet */
-static int suppressdup = 0; /* are we suppressing duplicate messages? */
+static bool suppressdup; /* are we suppressing duplicate messages? */
-static int verbose = 0;
-static int debug = 0;
+static bool verbose;
+static bool debug;
static char *addr = NULL;
static char *user = NULL;
static int parse (int);
static void expand (char *, char *, int);
static void glob (int);
-static struct pair *lookup (struct pair *, char *);
+static struct pair *lookup (struct pair *, char *) PURE;
static int logged_in (void);
static int timely (char *, char *);
static int usr_file (int, char *, int);
static void alrmser (int);
static void get_sender (char *, char **);
static int copy_message (int, char *, int);
-static void verbose_printf (char *fmt, ...);
-static void adorn (char *, char *, ...);
-static void debug_printf (char *fmt, ...);
+static void verbose_printf (char *fmt, ...) CHECK_PRINTF(1, 2);
+static void adorn (char *, char *, ...) CHECK_PRINTF(2, 3);
+static void debug_printf (char *fmt, ...) CHECK_PRINTF(1, 2);
static int suppress_duplicates (int, char *);
static char *trim (char *);
char mailbox[BUFSIZ], tmpfil[BUFSIZ];
char **argp, **arguments;
- if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; }
+ if (nmh_init(argv[0], false, false)) { return 1; }
mts_init ();
arguments = getarguments (invo_name, argc, argv, 0);
ambigsw (cp, switches);
done (1);
case UNKWNSW:
- adios (NULL, "-%s unknown", cp);
+ die("-%s unknown", cp);
case HELPSW:
snprintf (buf, sizeof(buf), "%s [switches]", invo_name);
case ADDRSW:
if (!(addr = *argp++))/* allow -xyz arguments */
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case INFOSW:
if (!(info = *argp++))/* allow -xyz arguments */
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case USERSW:
if (!(user = *argp++))/* allow -xyz arguments */
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case FILESW:
if (!(file = *argp++) || *file == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case SENDERSW:
if (!(sender = *argp++))/* allow -xyz arguments */
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case MAILBOXSW:
if (!(mbox = *argp++) || *mbox == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case HOMESW:
if (!(home = *argp++) || *home == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
continue;
case MAILSW:
if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
+ die("missing argument to %s", argp[-2]);
if (mdlvr)
- adios (NULL, "only one maildelivery file at a time!");
+ die("only one maildelivery file at a time!");
mdlvr = cp;
continue;
case VERBSW:
- verbose++;
+ verbose = true;
continue;
case NVERBSW:
- verbose = 0;
+ verbose = false;
continue;
case SUPPRESSDUP:
- suppressdup++;
+ suppressdup = true;
continue;
case NSUPPRESSDUP:
- suppressdup = 0;
+ suppressdup = false;
continue;
case DEBUGSW:
- debug++;
+ debug = true;
continue;
}
} else {
- adios (NULL, "only switch arguments are supported");
+ die("only switch arguments are supported");
}
}
user = getusername ();
}
if ((pw = getpwnam (user)) == NULL)
- adios (NULL, "no such local user as %s", user);
+ die("no such local user as %s", user);
if (chdir (pw->pw_dir) == -1)
if (chdir ("/") < 0) {
/* Record the delivery time */
if ((now = dlocaltimenow ()) == NULL)
- adios (NULL, "unable to ascertain local time");
+ die("unable to ascertain local time");
snprintf (ddate, sizeof(ddate), "Delivery-Date: %s\n", dtimenow (0));
/*
if (debug)
debug_printf ("retrieving message from file \"%s\"\n", file);
if ((fd = copy_message (tempfd, tmpfil, 1)) == -1)
- adios(NULL, "unable to create temporary file in %s",
+ die("unable to create temporary file in %s",
get_temp_dir());
close (tempfd);
} else {
if (debug)
debug_printf ("retrieving message from stdin\n");
if ((fd = copy_message (fileno (stdin), tmpfil, 1)) == -1)
- adios(NULL, "unable to create temporary file in %s",
+ die("unable to create temporary file in %s",
get_temp_dir());
}
(void) m_unlink (tmpfil);
if (!(fp = fdopen (fd, "r+")))
- adios (NULL, "unable to access temporary file");
+ die("unable to access temporary file");
/*
* If no sender given, extract it
static int
usr_delivery (int fd, char *delivery, int su)
{
- int i, accept, status=1, won, vecp, next;
+ int i;
+ bool accept;
+ int status=1;
+ bool won;
+ int vecp;
+ bool next;
char *field, *pattern, *action, *result, *string;
char buffer[BUFSIZ], tmpbuf[BUFSIZ];
char *vec[NVEC];
return -1;
}
- won = 0;
- next = 1;
+ won = false;
+ next = true;
/* read and process delivery file */
while (fgets (buffer, sizeof(buffer), fp)) {
if (*buffer == '#' || *buffer == '\n')
continue;
- TrimSuffixC(buffer, '\n');
+ trim_suffix_c(buffer, '\n');
/* split buffer into fields */
vecp = split (buffer, vec);
* do this - else fall through
*/
if (!next)
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case '?':
/*
* consider delivered if action is successful.
*/
if (won)
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case 'A':
case 'a':
* Take action, and consider delivered if
* action is successful.
*/
- accept = 1;
+ accept = true;
break;
case 'R':
* Take action, but don't consider delivered, even
* if action is successful
*/
- accept = 0;
+ accept = false;
break;
}
if (won)
continue;
break;
- } /* else fall */
+ }
+ /* FALLTHRU */
default:
/* parse message and build lookup table */
*/
if ((p = lookup (hdrs, field)) && (p->p_value != NULL)
&& matches (p->p_value, pattern)) {
- next = 1;
+ next = true;
} else {
- next = 0;
+ next = false;
continue;
}
break;
case 'q':
/* deliver to quoted pipe */
if (strcasecmp (action, "qpipe"))
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case '^':
expand (tmpbuf, string, fd);
if (split (tmpbuf, vec) < 1)
case 'p':
/* deliver to pipe */
if (strcasecmp (action, "pipe"))
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case '|':
vec[2] = "sh";
vec[3] = "-c";
}
/* deliver to nmh folder */
else if (strcasecmp (action, "folder"))
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case '+':
status = usr_folder (fd, string);
break;
}
/* mbox format */
else if (strcasecmp (action, "mbox"))
- continue; /* else fall */
+ continue;
+ /* FALLTHRU */
case '>':
/* mbox format */
break;
}
- if (status) next = 0; /* action failed, mark for 'N' result */
+ if (status) next = false; /* action failed, mark for 'N' result */
if (accept && status == 0)
- won++;
+ won = true;
}
fclose (fp);
- return (won ? 0 : -1);
+ return won ? 0 : -1;
}
int i, state;
int fd1;
char *cp, *dp, *lp;
- char name[NAMESZ], field[BUFSIZ];
+ char name[NAMESZ], field[NMH_BUFSIZ];
struct pair *p, *q;
FILE *in;
- m_getfld_state_t gstate = 0;
+ m_getfld_state_t gstate;
if (parsed++)
return 0;
* Scan the headers of the message and build
* a lookup table.
*/
+ gstate = m_getfld_state_init(in);
for (i = 0;;) {
int fieldsz = sizeof field;
- switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) {
+ switch (state = m_getfld2(&gstate, name, field, &fieldsz)) {
case FLD:
case FLDPLUS:
lp = mh_xstrdup(field);
while (state == FLDPLUS) {
fieldsz = sizeof field;
- state = m_getfld (&gstate, name, field, &fieldsz, in);
+ state = m_getfld2(&gstate, name, field, &fieldsz);
lp = add (field, lp);
}
for (p = hdrs; p->p_name; p++) {
case LENERR:
case FMTERR:
- advise (NULL, "format error in message");
+ inform("format error in message");
break;
default:
- advise (NULL, "internal error in m_getfld");
+ inform("internal error in m_getfld2");
fclose (in);
return -1;
}
p->p_value = getcpy (q ? q->p_value : "");
p->p_flags &= ~P_CHK;
if (debug)
- debug_printf ("vars[%d]: name=\"%s\" value=\"%s\"\n",
- p - vars, p->p_name, trim(p->p_value));
+ debug_printf ("vars[%td]: name=\"%s\" value=\"%s\"\n",
+ p - vars, p->p_name, trim(p->p_value));
}
if (debug) {
for (p = hdrs; p->p_name; p++)
- debug_printf ("hdrs[%d]: name=\"%s\" value=\"%s\"\n",
+ debug_printf ("hdrs[%td]: name=\"%s\" value=\"%s\"\n",
p - hdrs, p->p_name, p->p_value ? trim(p->p_value) : "");
}
if (debug) {
for (p = vars; p->p_name; p++)
- debug_printf ("vars[%d]: name=\"%s\" value=\"%s\"\n",
+ debug_printf ("vars[%td]: name=\"%s\" value=\"%s\"\n",
p - vars, p->p_name, trim(p->p_value));
}
}
if (debug)
continue;
endutxent();
- return (utmped = DONE);
+ return utmped = DONE;
}
}
endutxent();
#endif /* HAVE_GETUTXENT */
- return (utmped = NOTOK);
+ return utmped = NOTOK;
}
#define check(t,a,b) if (t < a || t > b) return -1
static int
usr_file (int fd, char *mailbox, int mbx_style)
{
- int md, mapping;
-
- if (verbose)
- verbose_printf ("delivering to file \"%s\"", mailbox);
+ int md;
- if (mbx_style == MBOX_FORMAT) {
- if (verbose)
- verbose_printf (" (mbox style)");
- mapping = 0;
- } else {
- if (verbose)
- verbose_printf (" (mmdf style)");
- mapping = 1;
+ if (verbose) {
+ verbose_printf("delivering to file \"%s\" (%s style)", mailbox,
+ mbx_style == MBOX_FORMAT ? "mbox" : "mmdf");
}
/* open and lock the file */
return -1;
}
- lseek (fd, (off_t) 0, SEEK_SET);
+ lseek(fd, 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, NULL) == -1) {
if (verbose)
adorn ("", "error writing to:");
return -1;
{
volatile int fd = fd_arg;
pid_t child_id;
- int i, bytes, seconds, status;
+ int bytes, seconds, status;
struct stat st;
if (verbose && !suppress)
verbose_printf ("delivering to pipe \"%s\"", cmd);
- lseek (fd, (off_t) 0, SEEK_SET);
-
- for (i = 0; (child_id = fork()) == -1 && i < 5; i++)
- sleep (5);
+ lseek(fd, 0, SEEK_SET);
+ child_id = fork();
switch (child_id) {
case -1:
/* fork error */
}
#endif /* TIOCNOTTY */
- setpgid ((pid_t) 0, getpid ()); /* put in own process group */
+ setpgid(0, getpid()); /* put in own process group */
*environ = NULL;
- m_putenv ("USER", pw->pw_name);
- m_putenv ("HOME", pw->pw_dir);
- m_putenv ("SHELL", pw->pw_shell);
+ setenv("USER", pw->pw_name, 1);
+ setenv("HOME", pw->pw_dir, 1);
+ setenv("SHELL", pw->pw_shell, 1);
execvp (pgm, vec);
- _exit (-1);
+ _exit(1);
default:
/* parent process */
if (verbose) {
if (status == 0)
verbose_printf (", success.\n");
- else
- if ((status & 0xff00) == 0xff00)
- verbose_printf (", system error\n");
- else
- pidstatus (status, stdout, ", failed");
+ else if ((status & 0xff00) == 0xff00)
+ verbose_printf (", system error\n");
+ else
+ pidstatus (status, stdout, ", failed");
}
- return (status == 0 ? 0 : -1);
+ return status == 0 ? 0 : -1;
}
/*
* Ruthlessly kill the child and anything
}
if (i == -1)
goto you_lose;
- lseek (fd1, (off_t) 0, SEEK_SET);
+ lseek(fd1, 0, SEEK_SET);
return fd1;
}
while (fgets (buffer, sizeof(buffer), qfp)) {
if (first) {
first = 0;
- if (HasPrefix(buffer, "From ")) {
+ if (has_prefix(buffer, "From ")) {
/* get copy of envelope information ("From " line) */
envelope = mh_xstrdup(buffer);
return -1;
}
fclose (qfp);
- lseek (fd1, (off_t) 0, SEEK_SET);
+ lseek(fd1, 0, SEEK_SET);
return fd1;
static char *
trim (char *cp)
{
- char buffer[BUFSIZ*4];
+ static char buffer[BUFSIZ * 4];
char *bp, *sp;
if (cp == NULL)
if (isspace((unsigned char) *sp))
*sp = ' ';
- /* now return a copy */
- return mh_xstrdup(bp);
+ return bp;
}
/*
char *s;
eindex = errno; /* save the errno */
- printf(", ");
+ fputs(", ", stdout);
va_start(ap, fmt);
vprintf(fmt, ap);
suppress_duplicates (int fd, char *file)
{
int fd1, lockfd, state, result;
- char *cp, buf[BUFSIZ], name[NAMESZ];
+ char *cp, buf[NMH_BUFSIZ], name[NAMESZ];
datum key, value;
DBM *db;
FILE *in;
- m_getfld_state_t gstate = 0;
+ m_getfld_state_t gstate;
if ((fd1 = dup (fd)) == -1)
return -1;
}
rewind (in);
+ gstate = m_getfld_state_init(in);
for (;;) {
int failed_to_lock = 0;
int bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, in);
+ state = m_getfld2(&gstate, name, buf, &bufsz);
switch (state) {
case FLD:
case FLDPLUS:
if (strcasecmp (name, "Message-ID")) {
while (state == FLDPLUS) {
bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, in);
+ state = m_getfld2(&gstate, name, buf, &bufsz);
}
continue;
}
cp = mh_xstrdup(buf);
while (state == FLDPLUS) {
bufsz = sizeof buf;
- state = m_getfld (&gstate, name, buf, &bufsz, in);
+ state = m_getfld2(&gstate, name, buf, &bufsz);
cp = add (buf, cp);
}
key.dptr = trimcpy (cp);