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