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 32 static void munset ARGS((mbox_t *mlist)); /* free mlist and mval */ 33 static mbox_t * mballoc ARGS((char *p, char *m)); /* allocate a new mbox */ 34 static void mprintit ARGS((mbox_t *mbp)); 35 36 void 37 mcheck() 38 { 39 register mbox_t *mbp; 40 time_t now; 41 long mailcheck; 42 struct tbl *vp; 43 struct stat stbuf; 44 45 if (getint(global("MAILCHECK"), &mailcheck) < 0) 46 return; 47 48 now = time((time_t *) 0); 49 if (mlastchkd == 0) 50 mlastchkd = now; 51 if (now - mlastchkd >= mailcheck) { 52 mlastchkd = now; 53 54 vp = global("MAILPATH"); 55 if (vp && (vp->flag & ISSET)) 56 mbp = mplist; 57 else if ((vp = global("MAIL")) && (vp->flag & ISSET)) 58 mbp = &mbox; 59 else 60 mbp = NULL; 61 62 while (mbp) { 63 if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0 64 && S_ISREG(stbuf.st_mode)) 65 { 66 if (stbuf.st_size 67 && mbp->mb_mtime != stbuf.st_mtime 68 && stbuf.st_atime <= stbuf.st_mtime) 69 mprintit(mbp); 70 mbp->mb_mtime = stbuf.st_mtime; 71 } else { 72 /* 73 * Some mail readers remove the mail 74 * file if all mail is read. If file 75 * does not exist, assume this is the 76 * case and set mtime to zero. 77 */ 78 mbp->mb_mtime = 0; 79 } 80 mbp = mbp->mb_next; 81 } 82 } 83 } 84 85 void 86 mbset(p) 87 register char *p; 88 { 89 struct stat stbuf; 90 91 if (mbox.mb_msg) 92 afree((void *)mbox.mb_msg, APERM); 93 mbox.mb_path = p; 94 mbox.mb_msg = NULL; 95 if (p && stat(p,&stbuf) == 0 && S_ISREG(stbuf.st_mode)) 96 mbox.mb_mtime = stbuf.st_mtime; 97 else 98 mbox.mb_mtime = 0; 99 } 100 101 void 102 mpset(mptoparse) 103 register char *mptoparse; 104 { 105 register mbox_t *mbp; 106 register char *mpath, *mmsg, *mval; 107 char *p; 108 109 munset( mplist ); 110 mplist = NULL; 111 mval = str_save(mptoparse, APERM); 112 while (mval) { 113 mpath = mval; 114 if ((mval = strchr(mval, PATHSEP)) != NULL) { 115 *mval = '\0', mval++; 116 } 117 /* POSIX/bourne-shell say file%message */ 118 for (p = mpath; (mmsg = strchr(p, '%')); ) { 119 /* a literal percent? (POSIXism) */ 120 if (mmsg[-1] == '\\') { 121 /* use memmove() to avoid overlap problems */ 122 memmove(mmsg - 1, mmsg, strlen(mmsg) + 1); 123 p = mmsg + 1; 124 continue; 125 } 126 break; 127 } 128 /* at&t ksh says file?message */ 129 if (!mmsg && !Flag(FPOSIX)) 130 mmsg = strchr(mpath, '?'); 131 if (mmsg) { 132 *mmsg = '\0'; 133 mmsg++; 134 } 135 mbp = mballoc(mpath, mmsg); 136 mbp->mb_next = mplist; 137 mplist = mbp; 138 } 139 } 140 141 static void 142 munset(mlist) 143 register mbox_t *mlist; 144 { 145 register mbox_t *mbp; 146 147 while (mlist != NULL) { 148 mbp = mlist; 149 mlist = mbp->mb_next; 150 if (!mlist) 151 afree((void *)mbp->mb_path, APERM); 152 afree((void *)mbp, APERM); 153 } 154 } 155 156 static mbox_t * 157 mballoc(p, m) 158 char *p; 159 char *m; 160 { 161 struct stat stbuf; 162 register mbox_t *mbp; 163 164 mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM); 165 mbp->mb_next = NULL; 166 mbp->mb_path = p; 167 mbp->mb_msg = m; 168 if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) 169 mbp->mb_mtime = stbuf.st_mtime; 170 else 171 mbp->mb_mtime = 0; 172 return(mbp); 173 } 174 175 static void 176 mprintit( mbp ) 177 mbox_t *mbp; 178 { 179 struct tbl *vp; 180 181 setstr((vp = local("_", FALSE)), mbp->mb_path); 182 183 shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0)); 184 185 unset(vp, 0); 186 } 187 #endif /* KSH */ 188