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