10 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
11 #define MIN(a, b) ((a) < (b) ? (a) : (b))
12 #define MAXLINE (1 << 7)
13 #define BUFSIZE (1 << 12)
14 #define PAGER "pgmail"
15 #define NHEAD (1 << 4)
18 static char *hdr_filt
[] = {
19 "Subject:", "From:", "To:", "Cc:", "Date:", "User-Agent:",
20 "X-Mailer", "Organization"};
22 static struct mbox
*mbox
;
23 static struct sort
*sort
;
26 static int read_line(char *dst
, int size
)
28 static char buf
[BUFSIZE
];
33 int cur_len
= MIN(len
- cur
, size
- nw
- 1);
34 char *nl
= memchr(buf
+ cur
, '\n', cur_len
);
35 int nr
= nl
? nl
- buf
- cur
+ 1 : cur_len
;
37 memcpy(dst
+ nw
, buf
+ cur
, nr
);
42 if (nl
|| nw
== size
- 1)
45 if ((len
= read(STDIN_FILENO
, buf
, BUFSIZE
)) <= 0)
51 static char *till_eol(char *r
, int len
, char *s
)
54 while (r
< d
&& *s
&& *s
!= '\r' && *s
!= '\n')
59 static char *cut_word(char *dst
, char *s
)
69 static int msg_num(char *num
)
72 if (!*num
|| !strcmp(".", num
))
76 if (!strcmp("$", num
))
78 if (n
< 0 || n
>= mbox
->n
)
84 static void cmd_page(char *args
)
92 args
= cut_word(num
, args
);
93 if (msg_num(num
) == -1)
95 mail
= sort
->mails
[cur
];
96 mail
->stat
|= STAT_READ
;
98 if (!(pid
= fork())) {
99 char *args
[] = {PAGER
, NULL
};
101 dup2(fds
[0], STDIN_FILENO
);
106 hdr_len
= mail_head(mail
, head
, sizeof(head
),
107 hdr_filt
, ARRAY_SIZE(hdr_filt
));
108 write(fds
[1], head
, hdr_len
);
109 write(fds
[1], mail
->body
, mail
->body_len
);
111 waitpid(pid
, NULL
, 0);
114 static char *cut_cmd(char *dst
, char *s
)
116 while (isalpha(*s
)) {
123 static char *put_int(char *s
, int n
, int w
)
126 for (i
= 0; i
< w
; i
++) {
127 s
[w
- i
- 1] = n
|| !i
? '0' + n
% 10 : ' ';
133 static void cmd_head(char *args
)
138 args
= cut_word(num
, args
);
139 if (msg_num(num
) == -1)
141 beg
= cur
/ NHEAD
* NHEAD
;
142 end
= MIN(beg
+ NHEAD
, mbox
->n
);
143 for (i
= beg
; i
< end
; i
++) {
144 struct mail
*mail
= sort
->mails
[i
];
147 *s
++ = i
== cur
? '>' : ' ';
148 if (mail
->stat
& STAT_READ
)
151 *s
++ = mail
->stat
& STAT_NEW
? 'N' : 'O';
152 s
= put_int(s
, i
, DIGITS
);
156 s
= sort_draw(sort
, i
, s
, 32);
159 s
= till_eol(s
, 40, mail
->subj_hdr
+ 9);
161 write(STDOUT_FILENO
, fmt
, s
- fmt
);
165 static void print(char *s
)
167 write(STDOUT_FILENO
, s
, strlen(s
));
170 static void cmd_fold(char *args
)
173 char *s
= put_int(msg
, mbox
->n
, DIGITS
);
174 strcpy(s
, " messages\n");
178 static void cmd_inc(char *args
)
183 static void prompt(void)
185 write(STDOUT_FILENO
, "? ", 2);
188 static void loop(void)
193 while (read_line(line
, sizeof(line
)) > 0) {
194 char *args
= cut_cmd(cmd
, line
);
195 int len
= strlen(cmd
);
197 if (cur
+ 1 < mbox
->n
) {
206 if (!strncmp("page", cmd
, len
))
208 if (!strncmp("header", cmd
, len
))
210 if (!strncmp("folder", cmd
, len
))
212 if (!strncmp("inc", cmd
, len
))
214 if (!strncmp("quit", cmd
, len
)) {
218 if (!strncmp("xit", cmd
, len
) || !strncmp("exit", cmd
, len
))
224 int main(int argc
, char *argv
[])
227 char *filename
= NULL
;
229 if (!strcmp("-f", argv
[i
]))
230 filename
= argv
[++i
];
232 mbox
= mbox_alloc(filename
);
233 sort
= sort_alloc(mbox
);