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