**
*/
-/* 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
-*/
-
#include <h/mh.h>
#include <h/rcvmail.h>
#include <h/signals.h>
#include <h/tws.h>
#include <h/utils.h>
-
#include <pwd.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <sysexits.h>
#ifdef INITGROUPS_HEADER
#include INITGROUPS_HEADER
extern int initgroups(char*, int);
#endif
-#include <utmp.h>
-
-#ifndef HAVE_GETUTENT
-# ifndef UTMP_FILE
-# ifdef _PATH_UTMP
-# define UTMP_FILE _PATH_UTMP
-# else
-# define UTMP_FILE "/etc/utmp"
-# endif
-# endif
-#endif
-
static struct swit switches[] = {
#define ADDRSW 0
{ "addr address", 0 },
#define VERBSW 8
{ "verbose", 0 },
#define NVERBSW 9
- { "noverbose", 0 },
+ { "noverbose", 2 },
#define DEBUGSW 10
{ "debug", 0 },
#define VERSIONSW 11
- { "version", 0 },
+ { "Version", 0 },
#define HELPSW 12
{ "help", 0 },
{ NULL, 0 }
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 verbose = 0;
static int debug = 0;
static char ddate[BUFSIZ]; /* record the delivery date */
struct tws *now;
-static jmp_buf myctx;
+volatile sig_atomic_t eflag = 0; /* flag to indecate interrupt */
+static volatile pid_t child_id;
/* flags for pair->p_flags */
#define P_NIL 0x00
static void expand(char *, char *, int);
static void glob(int);
static struct pair *lookup(struct pair *, char *);
-static int logged_in(void);
-static int timely(char *, char *);
static int usr_file(int, char *);
static int usr_pipe(int, char *, char *, char **, int);
static int usr_folder(int, char *);
-static RETSIGTYPE alrmser(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 char *trim(char *);
+static char *trimstr(char *);
int
char mailbox[BUFSIZ], tmpfil[BUFSIZ];
char **argp, **arguments;
-#ifdef LOCALE
setlocale(LC_ALL, "");
-#endif
invo_name = mhbasename(*argv);
- /* foil search of user profile/context */
- if (context_foil(NULL) == -1) {
- done(1);
- }
arguments = getarguments(invo_name, argc, argv, 0);
argp = arguments;
switch (smatch(++cp, switches)) {
case AMBIGSW:
ambigsw(cp, switches);
- done(1);
+ exit(EX_USAGE);
case UNKWNSW:
- adios(NULL, "-%s unknown", cp);
+ adios(EX_USAGE, NULL, "-%s unknown", cp);
case HELPSW:
snprintf(buf, sizeof(buf), "%s [switches] [address info sender]", invo_name);
print_help(buf, switches, 0);
- done(1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
case VERSIONSW:
print_version(invo_name);
- done(1);
+ exit(argc == 2 ? EX_OK : EX_USAGE);
case ADDRSW:
if (!(addr = *argp++)) {
/* allow -xyz arguments */
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case INFOSW:
if (!(info = *argp++)) {
/* allow -xyz arguments */
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case USERSW:
if (!(user = *argp++)) {
/* allow -xyz arguments */
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case FILESW:
if (!(file = *argp++) || *file == '-') {
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case SENDERSW:
if (!(sender = *argp++)) {
/* allow -xyz arguments */
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case MAILBOXSW:
if (!(mbox = *argp++) || *mbox == '-') {
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case HOMESW:
if (!(home = *argp++) || *home == '-') {
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
continue;
case MAILSW:
if (!(cp = *argp++) || *cp == '-') {
- adios(NULL, "missing argument to %s",
+ adios(EX_USAGE, NULL, "missing argument to %s",
argp[-2]);
}
if (mdlvr) {
- adios(NULL, "only one maildelivery file at a time!");
+ adios(EX_USAGE, NULL, "only one maildelivery file at a time!");
}
mdlvr = cp;
continue;
user = (cp = strchr(addr, '.')) ? ++cp : addr;
}
if (!(pw = getpwnam(user))) {
- adios(NULL, "no such local user as %s", user);
+ adios(EX_NOUSER, NULL, "no such local user as %s", user);
}
if (chdir(pw->pw_dir) == -1) {
/* Record the delivery time */
if (!(now = dlocaltimenow())) {
- adios(NULL, "unable to ascertain local time");
+ adios(EX_OSERR, NULL, "unable to ascertain local time");
}
- snprintf(ddate, sizeof(ddate), "Delivery-Date: %s\n", dtimenow(0));
+ snprintf(ddate, sizeof(ddate), "Delivery-Date: %s\n", dtimenow());
/*
** Copy the message to a temporary file
/* getting message from file */
if ((tempfd = open(file, O_RDONLY)) == -1) {
- adios(file, "unable to open");
+ adios(EX_IOERR, file, "unable to open");
}
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");
+ adios(EX_CANTCREAT, NULL, "unable to create temporary file");
}
close(tempfd);
} else {
debug_printf("retrieving message from stdin\n");
}
if ((fd = copy_message(fileno(stdin), tmpfil, 1)) == -1) {
- adios(NULL, "unable to create temporary file");
+ adios(EX_CANTCREAT, NULL, "unable to create temporary file");
}
}
unlink(tmpfil);
if (!(fp = fdopen(fd, "r+"))) {
- adios(NULL, "unable to access temporary file");
+ adios(EX_IOERR, NULL, "unable to access temporary file");
}
/* If no sender given, extract it from envelope information. */
}
if (debug) {
- debug_printf("addr=\"%s\"\n", trim(addr));
- debug_printf("user=\"%s\"\n", trim(user));
- debug_printf("info=\"%s\"\n", trim(info));
- debug_printf("sender=\"%s\"\n", trim(sender));
+ debug_printf("addr=\"%s\"\n", trimstr(addr));
+ debug_printf("user=\"%s\"\n", trimstr(user));
+ debug_printf("info=\"%s\"\n", trimstr(info));
+ debug_printf("sender=\"%s\"\n", trimstr(sender));
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));
+ envelope ? trimstr(envelope) : "");
+ debug_printf("mbox=\"%s\"\n", trimstr(mbox));
+ debug_printf("home=\"%s\"\n", trimstr(home));
+ debug_printf("ddate=\"%s\"\n", trimstr(ddate));
debug_printf("now=%02d:%02d\n\n", now->tw_hour, now->tw_min);
}
/* deliver the message */
status = localmail(fd, mdlvr);
- done(status != -1 ? RCV_MOK : RCV_MBX);
- return 1;
+ return (status != -1 ? RCV_MOK : RCV_MBX);
}
if (debug) {
for (i = 0; vec[i]; i++) {
debug_printf("vec[%d]: \"%s\"\n",
- i, trim(vec[i]));
+ i, trimstr(vec[i]));
}
}
break;
}
- if (vecp > 5 && mh_strcasecmp(vec[5], "select")==0) {
- if (logged_in() != -1) {
- continue;
- }
- if (vecp > 7 && timely(vec[6], vec[7]) == -1) {
- continue;
- }
- }
-
/* check if the field matches */
switch (*field) {
case '*':
static int
parse(int fd)
{
- int i, state;
- int fd1;
+ enum state state;
+ struct field f = {{0}};
+ int i, fd1;
char *cp, *dp, *lp;
- char name[NAMESZ], field[BUFSIZ];
struct pair *p, *q;
FILE *in;
/*
** Scan the headers of the message and build a lookup table.
*/
- for (i = 0, state = FLD;;) {
- switch (state = m_getfld(state, name, field, sizeof(field),
- in)) {
- case FLD:
- case FLDEOF:
- case FLDPLUS:
- lp = getcpy(field);
- while (state == FLDPLUS) {
- state = m_getfld(state, name, field,
- sizeof(field), in);
- lp = add(field, lp);
- }
+ for (i = 0, state = FLD2;;) {
+ switch (state = m_getfld2(state, &f, in)) {
+ case FLD2:
+ lp = getcpy(f.value);
for (p = hdrs; p->p_name; p++) {
- if (mh_strcasecmp(p->p_name, name)!=0) {
+ if (mh_strcasecmp(p->p_name, f.name)!=0) {
if (!(p->p_flags & P_HID)) {
if ((cp = p->p_value)) {
if (p->p_flags & P_ADR) {
}
}
if (!p->p_name && i < NVEC) {
- p->p_name = getcpy(name);
+ p->p_name = getcpy(f.name);
p->p_value = lp;
p->p_flags = P_NIL;
p++, i++;
p->p_name = NULL;
}
- if (state != FLDEOF) {
- continue;
- }
- break;
+ continue;
- case BODY:
- case BODYEOF:
- case FILEEOF:
+ case BODY2:
+ case FILEEOF2:
break;
- case LENERR:
- case FMTERR:
+ case LENERR2:
+ case FMTERR2:
+ case IOERR2:
advise(NULL, "format error in message");
break;
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));
+ p - vars, p->p_name, trimstr(p->p_value));
}
}
if (debug) {
for (p = hdrs; p->p_name; p++) {
debug_printf("hdrs[%d]: name=\"%s\" value=\"%s\"\n",
p - hdrs, p->p_name,
- p->p_value ? trim(p->p_value) : "");
+ p->p_value ? trimstr(p->p_value) : "");
}
}
return 0;
if (debug) {
for (p = vars; p->p_name; p++) {
debug_printf("vars[%d]: name=\"%s\" value=\"%s\"\n",
- p - vars, p->p_name, trim(p->p_value));
+ p - vars, p->p_name, trimstr(p->p_value));
}
}
}
/*
-** Check utmp(x) file to see if user is currently
-** logged in.
-*/
-#ifdef HAVE_GETUTENT
-static int
-logged_in(void)
-{
- struct utmp * utp;
-
- if (utmped) {
- return utmped;
- }
- setutent();
-
- while ((utp = getutent())) {
- if (
-#ifdef HAVE_STRUCT_UTMP_UT_TYPE
- utp->ut_type == USER_PROCESS &&
-#endif
- utp->ut_name[0] != 0 &&
- strncmp(user, utp->ut_name,
- sizeof(utp->ut_name)) == 0) {
- if (debug) {
- continue;
- }
- endutent();
- return (utmped = DONE);
- }
- }
-
- endutent();
- return (utmped = NOTOK);
-}
-#else
-static int
-logged_in(void)
-{
- struct utmp ut;
- FILE *uf;
-
- if (utmped) {
- return utmped;
- }
- if (!(uf = fopen(UTMP_FILE, "r"))) {
- return NOTOK;
- }
- while (fread((char *) &ut, sizeof(ut), 1, uf) == 1) {
- if (ut.ut_name[0] && strncmp(user, ut.ut_name,
- sizeof(ut.ut_name))==0) {
- if (debug) {
- continue;
- }
- fclose(uf);
- return (utmped = DONE);
- }
- }
- fclose(uf);
- return (utmped = NOTOK);
-}
-#endif
-
-#define check(t,a,b) if ((t) < (a) || (t) > (b)) return -1
-#define cmpar(h1,m1,h2,m2) if ((h1)<(h2) || ((h1)==(h2) && (m1)<(m2))) \
- return 0
-
-static int
-timely(char *t1, char *t2)
-{
- int t1hours, t1mins, t2hours, t2mins;
-
- if (sscanf(t1, "%d:%d", &t1hours, &t1mins) != 2) {
- return -1;
- }
- check(t1hours, 0, 23);
- check(t1mins, 0, 59);
-
- if (sscanf(t2, "%d:%d", &t2hours, &t2mins) != 2) {
- return -1;
- }
- check(t2hours, 0, 23);
- check(t2mins, 0, 59);
-
- cmpar(now->tw_hour, now->tw_min, t1hours, t1mins);
- cmpar(t2hours, t2mins, now->tw_hour, now->tw_min);
-
- return -1;
-}
-
-
-/*
** Deliver message by appending to a file, using rcvpack(1).
*/
static int
static int
usr_pipe(int fd, char *cmd, char *pgm, char **vec, int suppress)
{
- pid_t child_id;
int bytes, seconds, status, n;
struct stat st;
char *path;
m_putenv("PATH", path);
execvp(pgm, vec);
- _exit(-1);
+ _exit(EX_OSERR);
default:
/* parent process */
- if (setjmp(myctx)) {
- /*
- ** Ruthlessly kill the child and anything
- ** else in its process group.
- */
- kill(-child_id, SIGKILL);
- if (verbose)
- verbose_printf(", timed-out; terminated\n");
- return -1;
- }
SIGNAL(SIGALRM, alrmser);
bytes = fstat(fd, &st) != -1 ? (int) st.st_size : 100;
status = pidwait(child_id, 0);
alarm(0);
+ if (eflag) {
+ if (verbose) {
+ verbose_printf(", timed-out; terminated\n");
+ }
+ return -1;
+ }
+
if (verbose) {
if (!status) {
verbose_printf(", success.\n");
}
-static RETSIGTYPE
+static void
alrmser(int i)
{
-#ifndef RELIABLE_SIGNALS
- SIGNAL(SIGALRM, alrmser);
-#endif
-
- longjmp(myctx, DONE);
+ eflag = 1;
+ kill(-child_id, SIGKILL);
}
i = strlen("From ");
strncpy(buffer, envelope + i, sizeof(buffer));
+ buffer[sizeof buffer -1] = '\0'; /* ensure termination */
if ((cp = strchr(buffer, '\n'))) {
*cp = '\0';
cp -= 24;
** Trim strings for pretty printing of debugging output
*/
static char *
-trim(char *cp)
+trimstr(char *cp)
{
char buffer[BUFSIZ*4];
unsigned char *bp, *sp;