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