1 /* $OpenBSD: mail.c,v 1.24 2018/06/25 15:22:30 cheloha Exp $ */
4 * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by
17 #define MBMESSAGE "you have mail in $_"
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 */
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
;
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
*);
45 struct timespec elapsed
, now
;
50 clock_gettime(CLOCK_MONOTONIC
, &now
);
55 timespecsub(&now
, &mlastchkd
, &elapsed
);
56 if (elapsed
.tv_sec
>= mailcheck_interval
) {
61 else if ((vp
= global("MAIL")) && (vp
->flag
& ISSET
))
67 if (mbp
->mb_path
&& stat(mbp
->mb_path
, &stbuf
) == 0 &&
68 S_ISREG(stbuf
.st_mode
)) {
70 mbp
->mb_mtime
!= stbuf
.st_mtime
&&
71 stbuf
.st_atime
<= stbuf
.st_mtime
)
73 mbp
->mb_mtime
= stbuf
.st_mtime
;
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.
89 mcset(int64_t interval
)
91 mailcheck_interval
= interval
;
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
);
104 if (p
&& stat(p
, &stbuf
) == 0 && S_ISREG(stbuf
.st_mode
))
105 mbox
.mb_mtime
= stbuf
.st_mtime
;
111 mpset(char *mptoparse
)
114 char *mpath
, *mmsg
, *mval
;
119 mval
= str_save(mptoparse
, APERM
);
122 if ((mval
= strchr(mval
, ':')) != NULL
) {
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);
137 /* at&t ksh says file?message */
138 if (!mmsg
&& !Flag(FPOSIX
))
139 mmsg
= strchr(mpath
, '?');
144 mbp
= mballoc(mpath
, mmsg
);
145 mbp
->mb_next
= mplist
;
151 munset(mbox_t
*mlist
)
155 while (mlist
!= NULL
) {
157 mlist
= mbp
->mb_next
;
159 afree(mbp
->mb_path
, APERM
);
165 mballoc(char *p
, char *m
)
170 mbp
= alloc(sizeof(mbox_t
), APERM
);
174 if (stat(mbp
->mb_path
, &stbuf
) == 0 && S_ISREG(stbuf
.st_mode
))
175 mbp
->mb_mtime
= stbuf
.st_mtime
;
182 mprintit(mbox_t
*mbp
)
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.
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));