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