2019-01-14 00:48:16 -08:00
|
|
|
/* $OpenBSD: mail.c,v 1.27 2019/01/14 08:48:16 schwarze Exp $ */
|
1996-08-13 23:19:10 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
|
|
|
|
* John R. MacMillan
|
|
|
|
*/
|
|
|
|
|
2004-12-18 12:55:52 -08:00
|
|
|
#include <sys/stat.h>
|
2018-06-25 08:22:30 -07:00
|
|
|
#include <sys/time.h>
|
2015-10-18 19:15:45 -07:00
|
|
|
|
2015-10-19 07:42:16 -07:00
|
|
|
#include <string.h>
|
2004-12-18 12:55:52 -08:00
|
|
|
#include <time.h>
|
1996-08-13 23:19:10 -07:00
|
|
|
|
2015-10-18 19:15:45 -07:00
|
|
|
#include "config.h"
|
|
|
|
#include "sh.h"
|
|
|
|
|
1996-08-13 23:19:10 -07:00
|
|
|
#define MBMESSAGE "you have mail in $_"
|
|
|
|
|
|
|
|
typedef struct mbox {
|
|
|
|
struct mbox *mb_next; /* next mbox in list */
|
|
|
|
char *mb_path; /* path to mail file */
|
|
|
|
char *mb_msg; /* to announce arrival of new mail */
|
|
|
|
time_t mb_mtime; /* mtime of mail file */
|
|
|
|
} mbox_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* $MAILPATH is a linked list of mboxes. $MAIL is a treated as a
|
|
|
|
* special case of $MAILPATH, where the list has only one node. The
|
|
|
|
* same list is used for both since they are exclusive.
|
|
|
|
*/
|
|
|
|
|
1999-06-14 18:18:32 -07:00
|
|
|
static mbox_t *mplist;
|
|
|
|
static mbox_t mbox;
|
2018-06-25 08:22:30 -07:00
|
|
|
static struct timespec mlastchkd; /* when mail was last checked */
|
1999-06-14 18:18:32 -07:00
|
|
|
static time_t mailcheck_interval;
|
1996-08-13 23:19:10 -07:00
|
|
|
|
2013-11-28 02:33:37 -08:00
|
|
|
static void munset(mbox_t *); /* free mlist and mval */
|
2004-12-20 03:34:26 -08:00
|
|
|
static mbox_t * mballoc(char *, char *); /* allocate a new mbox */
|
2013-11-28 02:33:37 -08:00
|
|
|
static void mprintit(mbox_t *);
|
1996-08-13 23:19:10 -07:00
|
|
|
|
|
|
|
void
|
2004-12-20 03:34:26 -08:00
|
|
|
mcheck(void)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
2004-12-18 13:25:44 -08:00
|
|
|
mbox_t *mbp;
|
2018-06-25 08:22:30 -07:00
|
|
|
struct timespec elapsed, now;
|
1996-08-13 23:19:10 -07:00
|
|
|
struct tbl *vp;
|
|
|
|
struct stat stbuf;
|
2018-06-25 08:22:30 -07:00
|
|
|
static int first = 1;
|
1996-08-13 23:19:10 -07:00
|
|
|
|
2019-01-07 12:50:43 -08:00
|
|
|
if (mplist)
|
|
|
|
mbp = mplist;
|
|
|
|
else if ((vp = global("MAIL")) && (vp->flag & ISSET))
|
|
|
|
mbp = &mbox;
|
|
|
|
else
|
|
|
|
mbp = NULL;
|
|
|
|
if (mbp == NULL)
|
|
|
|
return;
|
|
|
|
|
2018-06-25 08:22:30 -07:00
|
|
|
clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
|
if (first) {
|
1996-08-13 23:19:10 -07:00
|
|
|
mlastchkd = now;
|
2018-06-25 08:22:30 -07:00
|
|
|
first = 0;
|
|
|
|
}
|
|
|
|
timespecsub(&now, &mlastchkd, &elapsed);
|
|
|
|
if (elapsed.tv_sec >= mailcheck_interval) {
|
1996-08-13 23:19:10 -07:00
|
|
|
mlastchkd = now;
|
|
|
|
|
|
|
|
while (mbp) {
|
2005-03-30 09:16:37 -08:00
|
|
|
if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0 &&
|
|
|
|
S_ISREG(stbuf.st_mode)) {
|
|
|
|
if (stbuf.st_size &&
|
|
|
|
mbp->mb_mtime != stbuf.st_mtime &&
|
|
|
|
stbuf.st_atime <= stbuf.st_mtime)
|
1996-08-13 23:19:10 -07:00
|
|
|
mprintit(mbp);
|
|
|
|
mbp->mb_mtime = stbuf.st_mtime;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Some mail readers remove the mail
|
|
|
|
* file if all mail is read. If file
|
|
|
|
* does not exist, assume this is the
|
|
|
|
* case and set mtime to zero.
|
|
|
|
*/
|
|
|
|
mbp->mb_mtime = 0;
|
|
|
|
}
|
|
|
|
mbp = mbp->mb_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-14 18:18:32 -07:00
|
|
|
void
|
2018-04-09 10:53:36 -07:00
|
|
|
mcset(int64_t interval)
|
1999-06-14 18:18:32 -07:00
|
|
|
{
|
|
|
|
mailcheck_interval = interval;
|
|
|
|
}
|
|
|
|
|
1996-08-13 23:19:10 -07:00
|
|
|
void
|
2004-12-20 03:34:26 -08:00
|
|
|
mbset(char *p)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
|
|
|
struct stat stbuf;
|
|
|
|
|
2015-10-09 12:36:27 -07:00
|
|
|
afree(mbox.mb_msg, APERM);
|
|
|
|
afree(mbox.mb_path, APERM);
|
1998-06-25 12:01:27 -07:00
|
|
|
/* Save a copy to protect from export (which munges the string) */
|
|
|
|
mbox.mb_path = str_save(p, APERM);
|
1996-08-13 23:19:10 -07:00
|
|
|
mbox.mb_msg = NULL;
|
1998-06-25 12:01:27 -07:00
|
|
|
if (p && stat(p, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
|
1996-08-13 23:19:10 -07:00
|
|
|
mbox.mb_mtime = stbuf.st_mtime;
|
|
|
|
else
|
|
|
|
mbox.mb_mtime = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-12-20 03:34:26 -08:00
|
|
|
mpset(char *mptoparse)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
2004-12-18 13:25:44 -08:00
|
|
|
mbox_t *mbp;
|
|
|
|
char *mpath, *mmsg, *mval;
|
1996-08-13 23:19:10 -07:00
|
|
|
char *p;
|
|
|
|
|
|
|
|
munset( mplist );
|
|
|
|
mplist = NULL;
|
|
|
|
mval = str_save(mptoparse, APERM);
|
|
|
|
while (mval) {
|
|
|
|
mpath = mval;
|
2004-12-18 12:55:52 -08:00
|
|
|
if ((mval = strchr(mval, ':')) != NULL) {
|
2005-03-30 09:16:37 -08:00
|
|
|
*mval = '\0';
|
|
|
|
mval++;
|
1996-08-13 23:19:10 -07:00
|
|
|
}
|
|
|
|
/* POSIX/bourne-shell say file%message */
|
|
|
|
for (p = mpath; (mmsg = strchr(p, '%')); ) {
|
|
|
|
/* a literal percent? (POSIXism) */
|
2019-01-13 16:59:19 -08:00
|
|
|
if (mmsg > mpath && mmsg[-1] == '\\') {
|
1996-08-13 23:19:10 -07:00
|
|
|
/* use memmove() to avoid overlap problems */
|
|
|
|
memmove(mmsg - 1, mmsg, strlen(mmsg) + 1);
|
2019-01-14 00:48:16 -08:00
|
|
|
p = mmsg;
|
1996-08-13 23:19:10 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* at&t ksh says file?message */
|
|
|
|
if (!mmsg && !Flag(FPOSIX))
|
|
|
|
mmsg = strchr(mpath, '?');
|
|
|
|
if (mmsg) {
|
|
|
|
*mmsg = '\0';
|
|
|
|
mmsg++;
|
2019-01-14 00:48:16 -08:00
|
|
|
if (*mmsg == '\0')
|
|
|
|
mmsg = NULL;
|
1996-08-13 23:19:10 -07:00
|
|
|
}
|
2019-01-14 00:48:16 -08:00
|
|
|
if (*mpath == '\0')
|
|
|
|
continue;
|
1996-08-13 23:19:10 -07:00
|
|
|
mbp = mballoc(mpath, mmsg);
|
|
|
|
mbp->mb_next = mplist;
|
|
|
|
mplist = mbp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-20 03:34:26 -08:00
|
|
|
munset(mbox_t *mlist)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
2004-12-18 13:25:44 -08:00
|
|
|
mbox_t *mbp;
|
1996-08-13 23:19:10 -07:00
|
|
|
|
|
|
|
while (mlist != NULL) {
|
|
|
|
mbp = mlist;
|
|
|
|
mlist = mbp->mb_next;
|
|
|
|
if (!mlist)
|
2015-09-01 06:12:31 -07:00
|
|
|
afree(mbp->mb_path, APERM);
|
|
|
|
afree(mbp, APERM);
|
1996-08-13 23:19:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static mbox_t *
|
2004-12-20 03:34:26 -08:00
|
|
|
mballoc(char *p, char *m)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
|
|
|
struct stat stbuf;
|
2004-12-18 13:25:44 -08:00
|
|
|
mbox_t *mbp;
|
1996-08-13 23:19:10 -07:00
|
|
|
|
2015-09-17 07:21:33 -07:00
|
|
|
mbp = alloc(sizeof(mbox_t), APERM);
|
1996-08-13 23:19:10 -07:00
|
|
|
mbp->mb_next = NULL;
|
|
|
|
mbp->mb_path = p;
|
|
|
|
mbp->mb_msg = m;
|
|
|
|
if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
|
|
|
|
mbp->mb_mtime = stbuf.st_mtime;
|
|
|
|
else
|
|
|
|
mbp->mb_mtime = 0;
|
|
|
|
return(mbp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-20 03:34:26 -08:00
|
|
|
mprintit(mbox_t *mbp)
|
1996-08-13 23:19:10 -07:00
|
|
|
{
|
|
|
|
struct tbl *vp;
|
|
|
|
|
1997-11-16 04:07:28 -08:00
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
* I doubt this $_ overloading is bad in /bin/sh mode. Anyhow, we
|
|
|
|
* crash as the code looks now if we do not set vp. Now, this is
|
|
|
|
* easy to fix too, but I'd like to see what POSIX says before doing
|
|
|
|
* a change like that.
|
|
|
|
*/
|
1997-01-02 09:37:25 -08:00
|
|
|
if (!Flag(FSH))
|
1997-11-16 04:07:28 -08:00
|
|
|
#endif
|
1999-06-14 18:18:32 -07:00
|
|
|
/* Ignore setstr errors here (arbitrary) */
|
2004-12-22 09:14:34 -08:00
|
|
|
setstr((vp = local("_", false)), mbp->mb_path, KSH_RETURN_ERROR);
|
1996-08-13 23:19:10 -07:00
|
|
|
|
|
|
|
shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0));
|
|
|
|
|
|
|
|
unset(vp, 0);
|
|
|
|
}
|