9 #define MIN(a, b) ((a) < (b) ? (a) : (b))
10 #define MAXLINE (1 << 7)
11 #define BUFSIZE (1 << 12)
12 #define PAGER "pgmail"
13 #define NHEAD (1 << 4)
15 static char buf
[BUFSIZE
];
19 static int read_line(char *dst
, int size
)
23 int cur_len
= MIN(len
- cur
, size
- nw
- 1);
24 char *nl
= memchr(buf
+ cur
, '\n', cur_len
);
25 int nr
= nl
? nl
- buf
- cur
+ 1 : cur_len
;
27 memcpy(dst
+ nw
, buf
+ cur
, nr
);
32 if (nl
|| nw
== size
- 1)
35 if ((len
= read(STDIN_FILENO
, buf
, BUFSIZE
)) <= 0)
41 static void till_eol(char *s
)
44 while (*s
&& *s
!= '\r' && *s
!= '\n')
50 static char *cut_int(char *dst
, char *s
)
60 static void cmd_page(struct mbox
*mbox
, char *args
)
67 args
= cut_int(num
, args
);
70 if (n
< 0 && n
>= mbox
->n
)
72 mail
= &mbox
->mails
[n
];
75 if (!(pid
= fork())) {
76 char *args
[] = {PAGER
, NULL
};
78 dup2(fds
[0], STDIN_FILENO
);
83 write(fds
[1], mail
->head
, mail
->len
);
85 waitpid(pid
, NULL
, 0);
88 static char *cut_cmd(char *dst
, char *s
)
97 static char *put_int(char *s
, int n
, int w
)
100 for (i
= 0; i
< w
; i
++) {
101 s
[w
- i
- 1] = n
|| !i
? '0' + n
% 10 : ' ';
107 static void cmd_head(struct mbox
*mbox
, char *args
)
110 int beg
= mbox
->c
/ NHEAD
* NHEAD
;
111 int end
= MIN(beg
+ NHEAD
, mbox
->n
);
114 for (i
= beg
; i
< end
; i
++) {
117 *s
++ = i
== mbox
->c
? '>' : ' ';
118 s
= put_int(s
, i
, 5);
121 write(STDOUT_FILENO
, fmt
, strlen(fmt
));
122 if (mbox
->mails
[i
].subject
)
123 till_eol(mbox
->mails
[i
].subject
+ 9);
127 static void loop(struct mbox
*mbox
)
131 while (read_line(line
, sizeof(line
)) > 0) {
132 char *args
= cut_cmd(cmd
, line
);
133 int len
= strlen(cmd
);
134 if (!strncmp("header", cmd
, len
))
135 cmd_head(mbox
, args
);
136 if (!strncmp("page", cmd
, len
))
137 cmd_page(mbox
, args
);
138 if (!strncmp("quit", cmd
, len
))
140 if (!strncmp("x", cmd
, len
) || !strncmp("exit", cmd
, len
))
145 int main(int argc
, char *argv
[])
149 char *filename
= NULL
;
151 if (!strcmp("-f", argv
[i
]))
152 filename
= argv
[++i
];
154 mbox
= mbox_alloc(filename
);