mail.c revision 1.1 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