Home | History | Annotate | Line # | Download | only in ksh
mail.c revision 1.5
      1  1.5  jschauma /*	$NetBSD: mail.c,v 1.5 2006/01/15 18:16:30 jschauma Exp $	*/
      2  1.2       tls 
      3  1.1       jtc /*
      4  1.1       jtc  * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
      5  1.1       jtc  * John R. MacMillan
      6  1.1       jtc  */
      7  1.4       agc #include <sys/cdefs.h>
      8  1.4       agc 
      9  1.4       agc #ifndef lint
     10  1.5  jschauma __RCSID("$NetBSD: mail.c,v 1.5 2006/01/15 18:16:30 jschauma Exp $");
     11  1.4       agc #endif
     12  1.4       agc 
     13  1.1       jtc 
     14  1.1       jtc #include "config.h"
     15  1.1       jtc 
     16  1.1       jtc #ifdef KSH
     17  1.1       jtc #include "sh.h"
     18  1.1       jtc #include "ksh_stat.h"
     19  1.1       jtc #include "ksh_time.h"
     20  1.1       jtc 
     21  1.5  jschauma #define MBMESSAGE	"You have mail in $_"
     22  1.1       jtc 
     23  1.1       jtc typedef struct mbox {
     24  1.1       jtc 	struct mbox    *mb_next;	/* next mbox in list */
     25  1.1       jtc 	char	       *mb_path;	/* path to mail file */
     26  1.1       jtc 	char	       *mb_msg;		/* to announce arrival of new mail */
     27  1.1       jtc 	time_t		mb_mtime;	/* mtime of mail file */
     28  1.1       jtc } mbox_t;
     29  1.1       jtc 
     30  1.1       jtc /*
     31  1.1       jtc  * $MAILPATH is a linked list of mboxes.  $MAIL is a treated as a
     32  1.1       jtc  * special case of $MAILPATH, where the list has only one node.  The
     33  1.1       jtc  * same list is used for both since they are exclusive.
     34  1.1       jtc  */
     35  1.1       jtc 
     36  1.3   hubertf static mbox_t	*mplist;
     37  1.3   hubertf static mbox_t	mbox;
     38  1.1       jtc static time_t	mlastchkd;	/* when mail was last checked */
     39  1.3   hubertf static time_t	mailcheck_interval;
     40  1.1       jtc 
     41  1.1       jtc static void     munset      ARGS((mbox_t *mlist)); /* free mlist and mval */
     42  1.1       jtc static mbox_t * mballoc     ARGS((char *p, char *m)); /* allocate a new mbox */
     43  1.1       jtc static void     mprintit    ARGS((mbox_t *mbp));
     44  1.1       jtc 
     45  1.1       jtc void
     46  1.1       jtc mcheck()
     47  1.1       jtc {
     48  1.1       jtc 	register mbox_t	*mbp;
     49  1.1       jtc 	time_t		 now;
     50  1.1       jtc 	struct tbl	*vp;
     51  1.1       jtc 	struct stat	 stbuf;
     52  1.1       jtc 
     53  1.1       jtc 	now = time((time_t *) 0);
     54  1.1       jtc 	if (mlastchkd == 0)
     55  1.1       jtc 		mlastchkd = now;
     56  1.3   hubertf 	if (now - mlastchkd >= mailcheck_interval) {
     57  1.1       jtc 		mlastchkd = now;
     58  1.1       jtc 
     59  1.3   hubertf 		if (mplist)
     60  1.1       jtc 			mbp = mplist;
     61  1.1       jtc 		else if ((vp = global("MAIL")) && (vp->flag & ISSET))
     62  1.1       jtc 			mbp = &mbox;
     63  1.1       jtc 		else
     64  1.1       jtc 			mbp = NULL;
     65  1.1       jtc 
     66  1.1       jtc 		while (mbp) {
     67  1.1       jtc 			if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0
     68  1.1       jtc 			    && S_ISREG(stbuf.st_mode))
     69  1.1       jtc 			{
     70  1.1       jtc 				if (stbuf.st_size
     71  1.1       jtc 				    && mbp->mb_mtime != stbuf.st_mtime
     72  1.1       jtc 				    && stbuf.st_atime <= stbuf.st_mtime)
     73  1.1       jtc 					mprintit(mbp);
     74  1.1       jtc 				mbp->mb_mtime = stbuf.st_mtime;
     75  1.1       jtc 			} else {
     76  1.1       jtc 				/*
     77  1.1       jtc 				 * Some mail readers remove the mail
     78  1.1       jtc 				 * file if all mail is read.  If file
     79  1.1       jtc 				 * does not exist, assume this is the
     80  1.1       jtc 				 * case and set mtime to zero.
     81  1.1       jtc 				 */
     82  1.1       jtc 				mbp->mb_mtime = 0;
     83  1.1       jtc 			}
     84  1.1       jtc 			mbp = mbp->mb_next;
     85  1.1       jtc 		}
     86  1.1       jtc 	}
     87  1.1       jtc }
     88  1.1       jtc 
     89  1.1       jtc void
     90  1.3   hubertf mcset(interval)
     91  1.3   hubertf 	long interval;
     92  1.3   hubertf {
     93  1.3   hubertf 	mailcheck_interval = interval;
     94  1.3   hubertf }
     95  1.3   hubertf 
     96  1.3   hubertf void
     97  1.1       jtc mbset(p)
     98  1.1       jtc 	register char	*p;
     99  1.1       jtc {
    100  1.1       jtc 	struct stat	stbuf;
    101  1.1       jtc 
    102  1.1       jtc 	if (mbox.mb_msg)
    103  1.1       jtc 		afree((void *)mbox.mb_msg, APERM);
    104  1.3   hubertf 	if (mbox.mb_path)
    105  1.3   hubertf 		afree((void *)mbox.mb_path, APERM);
    106  1.3   hubertf 	/* Save a copy to protect from export (which munges the string) */
    107  1.3   hubertf 	mbox.mb_path = str_save(p, APERM);
    108  1.1       jtc 	mbox.mb_msg = NULL;
    109  1.3   hubertf 	if (p && stat(p, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
    110  1.1       jtc 		mbox.mb_mtime = stbuf.st_mtime;
    111  1.1       jtc 	else
    112  1.1       jtc 		mbox.mb_mtime = 0;
    113  1.1       jtc }
    114  1.1       jtc 
    115  1.1       jtc void
    116  1.1       jtc mpset(mptoparse)
    117  1.1       jtc 	register char	*mptoparse;
    118  1.1       jtc {
    119  1.1       jtc 	register mbox_t	*mbp;
    120  1.1       jtc 	register char	*mpath, *mmsg, *mval;
    121  1.1       jtc 	char *p;
    122  1.1       jtc 
    123  1.1       jtc 	munset( mplist );
    124  1.1       jtc 	mplist = NULL;
    125  1.1       jtc 	mval = str_save(mptoparse, APERM);
    126  1.1       jtc 	while (mval) {
    127  1.1       jtc 		mpath = mval;
    128  1.1       jtc 		if ((mval = strchr(mval, PATHSEP)) != NULL) {
    129  1.1       jtc 			*mval = '\0', mval++;
    130  1.1       jtc 		}
    131  1.1       jtc 		/* POSIX/bourne-shell say file%message */
    132  1.1       jtc 		for (p = mpath; (mmsg = strchr(p, '%')); ) {
    133  1.1       jtc 			/* a literal percent? (POSIXism) */
    134  1.1       jtc 			if (mmsg[-1] == '\\') {
    135  1.1       jtc 				/* use memmove() to avoid overlap problems */
    136  1.1       jtc 				memmove(mmsg - 1, mmsg, strlen(mmsg) + 1);
    137  1.1       jtc 				p = mmsg + 1;
    138  1.1       jtc 				continue;
    139  1.1       jtc 			}
    140  1.1       jtc 			break;
    141  1.1       jtc 		}
    142  1.1       jtc 		/* at&t ksh says file?message */
    143  1.1       jtc 		if (!mmsg && !Flag(FPOSIX))
    144  1.1       jtc 			mmsg = strchr(mpath, '?');
    145  1.1       jtc 		if (mmsg) {
    146  1.1       jtc 			*mmsg = '\0';
    147  1.1       jtc 			mmsg++;
    148  1.1       jtc 		}
    149  1.1       jtc 		mbp = mballoc(mpath, mmsg);
    150  1.1       jtc 		mbp->mb_next = mplist;
    151  1.1       jtc 		mplist = mbp;
    152  1.1       jtc 	}
    153  1.1       jtc }
    154  1.1       jtc 
    155  1.1       jtc static void
    156  1.1       jtc munset(mlist)
    157  1.1       jtc register mbox_t	*mlist;
    158  1.1       jtc {
    159  1.1       jtc 	register mbox_t	*mbp;
    160  1.1       jtc 
    161  1.1       jtc 	while (mlist != NULL) {
    162  1.1       jtc 		mbp = mlist;
    163  1.1       jtc 		mlist = mbp->mb_next;
    164  1.1       jtc 		if (!mlist)
    165  1.1       jtc 			afree((void *)mbp->mb_path, APERM);
    166  1.1       jtc 		afree((void *)mbp, APERM);
    167  1.1       jtc 	}
    168  1.1       jtc }
    169  1.1       jtc 
    170  1.1       jtc static mbox_t *
    171  1.1       jtc mballoc(p, m)
    172  1.1       jtc 	char	*p;
    173  1.1       jtc 	char	*m;
    174  1.1       jtc {
    175  1.1       jtc 	struct stat	stbuf;
    176  1.1       jtc 	register mbox_t	*mbp;
    177  1.1       jtc 
    178  1.1       jtc 	mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM);
    179  1.1       jtc 	mbp->mb_next = NULL;
    180  1.1       jtc 	mbp->mb_path = p;
    181  1.1       jtc 	mbp->mb_msg = m;
    182  1.1       jtc 	if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
    183  1.1       jtc 		mbp->mb_mtime = stbuf.st_mtime;
    184  1.1       jtc 	else
    185  1.1       jtc 		mbp->mb_mtime = 0;
    186  1.1       jtc 	return(mbp);
    187  1.1       jtc }
    188  1.1       jtc 
    189  1.1       jtc static void
    190  1.1       jtc mprintit( mbp )
    191  1.1       jtc mbox_t	*mbp;
    192  1.1       jtc {
    193  1.1       jtc 	struct tbl	*vp;
    194  1.1       jtc 
    195  1.3   hubertf 	/* Ignore setstr errors here (arbitrary) */
    196  1.3   hubertf 	setstr((vp = local("_", FALSE)), mbp->mb_path, KSH_RETURN_ERROR);
    197  1.1       jtc 
    198  1.1       jtc 	shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0));
    199  1.1       jtc 
    200  1.1       jtc 	unset(vp, 0);
    201  1.1       jtc }
    202  1.1       jtc #endif /* KSH */
    203