don't bother resolving onbld python module deps
[unleashed.git] / bin / ksh / mail.c
blobf4b31e0c3bf0668dbafb06f598bbad794e9080eb
1 /* $OpenBSD: mail.c,v 1.24 2018/06/25 15:22:30 cheloha Exp $ */
3 /*
4 * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
5 * John R. MacMillan
6 */
8 #include <sys/stat.h>
9 #include <sys/time.h>
11 #include <string.h>
12 #include <time.h>
14 #include "config.h"
15 #include "sh.h"
17 #define MBMESSAGE "you have mail in $_"
19 typedef struct mbox {
20 struct mbox *mb_next; /* next mbox in list */
21 char *mb_path; /* path to mail file */
22 char *mb_msg; /* to announce arrival of new mail */
23 time_t mb_mtime; /* mtime of mail file */
24 } mbox_t;
27 * $MAILPATH is a linked list of mboxes. $MAIL is a treated as a
28 * special case of $MAILPATH, where the list has only one node. The
29 * same list is used for both since they are exclusive.
32 static mbox_t *mplist;
33 static mbox_t mbox;
34 static struct timespec mlastchkd; /* when mail was last checked */
35 static time_t mailcheck_interval;
37 static void munset(mbox_t *); /* free mlist and mval */
38 static mbox_t * mballoc(char *, char *); /* allocate a new mbox */
39 static void mprintit(mbox_t *);
41 void
42 mcheck(void)
44 mbox_t *mbp;
45 struct timespec elapsed, now;
46 struct tbl *vp;
47 struct stat stbuf;
48 static int first = 1;
50 clock_gettime(CLOCK_MONOTONIC, &now);
51 if (first) {
52 mlastchkd = now;
53 first = 0;
55 timespecsub(&now, &mlastchkd, &elapsed);
56 if (elapsed.tv_sec >= mailcheck_interval) {
57 mlastchkd = now;
59 if (mplist)
60 mbp = mplist;
61 else if ((vp = global("MAIL")) && (vp->flag & ISSET))
62 mbp = &mbox;
63 else
64 mbp = NULL;
66 while (mbp) {
67 if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0 &&
68 S_ISREG(stbuf.st_mode)) {
69 if (stbuf.st_size &&
70 mbp->mb_mtime != stbuf.st_mtime &&
71 stbuf.st_atime <= stbuf.st_mtime)
72 mprintit(mbp);
73 mbp->mb_mtime = stbuf.st_mtime;
74 } else {
76 * Some mail readers remove the mail
77 * file if all mail is read. If file
78 * does not exist, assume this is the
79 * case and set mtime to zero.
81 mbp->mb_mtime = 0;
83 mbp = mbp->mb_next;
88 void
89 mcset(int64_t interval)
91 mailcheck_interval = interval;
94 void
95 mbset(char *p)
97 struct stat stbuf;
99 afree(mbox.mb_msg, APERM);
100 afree(mbox.mb_path, APERM);
101 /* Save a copy to protect from export (which munges the string) */
102 mbox.mb_path = str_save(p, APERM);
103 mbox.mb_msg = NULL;
104 if (p && stat(p, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
105 mbox.mb_mtime = stbuf.st_mtime;
106 else
107 mbox.mb_mtime = 0;
110 void
111 mpset(char *mptoparse)
113 mbox_t *mbp;
114 char *mpath, *mmsg, *mval;
115 char *p;
117 munset( mplist );
118 mplist = NULL;
119 mval = str_save(mptoparse, APERM);
120 while (mval) {
121 mpath = mval;
122 if ((mval = strchr(mval, ':')) != NULL) {
123 *mval = '\0';
124 mval++;
126 /* POSIX/bourne-shell say file%message */
127 for (p = mpath; (mmsg = strchr(p, '%')); ) {
128 /* a literal percent? (POSIXism) */
129 if (mmsg[-1] == '\\') {
130 /* use memmove() to avoid overlap problems */
131 memmove(mmsg - 1, mmsg, strlen(mmsg) + 1);
132 p = mmsg + 1;
133 continue;
135 break;
137 /* at&t ksh says file?message */
138 if (!mmsg && !Flag(FPOSIX))
139 mmsg = strchr(mpath, '?');
140 if (mmsg) {
141 *mmsg = '\0';
142 mmsg++;
144 mbp = mballoc(mpath, mmsg);
145 mbp->mb_next = mplist;
146 mplist = mbp;
150 static void
151 munset(mbox_t *mlist)
153 mbox_t *mbp;
155 while (mlist != NULL) {
156 mbp = mlist;
157 mlist = mbp->mb_next;
158 if (!mlist)
159 afree(mbp->mb_path, APERM);
160 afree(mbp, APERM);
164 static mbox_t *
165 mballoc(char *p, char *m)
167 struct stat stbuf;
168 mbox_t *mbp;
170 mbp = alloc(sizeof(mbox_t), APERM);
171 mbp->mb_next = NULL;
172 mbp->mb_path = p;
173 mbp->mb_msg = m;
174 if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode))
175 mbp->mb_mtime = stbuf.st_mtime;
176 else
177 mbp->mb_mtime = 0;
178 return(mbp);
181 static void
182 mprintit(mbox_t *mbp)
184 struct tbl *vp;
186 #if 0
188 * I doubt this $_ overloading is bad in /bin/sh mode. Anyhow, we
189 * crash as the code looks now if we do not set vp. Now, this is
190 * easy to fix too, but I'd like to see what POSIX says before doing
191 * a change like that.
193 if (!Flag(FSH))
194 #endif
195 /* Ignore setstr errors here (arbitrary) */
196 setstr((vp = local("_", false)), mbp->mb_path, KSH_RETURN_ERROR);
198 shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0));
200 unset(vp, 0);