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