let page command take mail number
[mailx.git] / mailx.c
blob7cae5135f5047bd87fb91064910187367d22db9e
1 #include <ctype.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include "mbox.h"
9 #define MIN(a, b) ((a) < (b) ? (a) : (b))
10 #define MAXLINE (1 << 7)
11 #define BUFSIZE (1 << 12)
12 #define PAGER "pgmail"
14 static char buf[BUFSIZE];
15 static int cur;
16 static int len;
18 static int read_line(char *dst, int size)
20 int nw = 0;
21 while (1) {
22 int cur_len = MIN(len - cur, size - nw - 1);
23 char *nl = memchr(buf + cur, '\n', cur_len);
24 int nr = nl ? nl - buf - cur + 1 : cur_len;
25 if (nr) {
26 memcpy(dst + nw, buf + cur, nr);
27 nw += nr;
28 cur += nr;
29 dst[nw] = '\0';
31 if (nl || nw == size - 1)
32 return nw;
33 cur = 0;
34 if ((len = read(STDIN_FILENO, buf, BUFSIZE)) <= 0)
35 return -1;
37 return nw;
40 static void till_eol(char *s)
42 char *r = s;
43 while (*s && *s != '\r' && *s != '\n')
44 s++;
45 write(1, r, s - r);
46 write(1, "\n", 1);
49 static char *cut_int(char *dst, char *s)
51 while (isspace(*s))
52 s++;
53 while (isdigit(*s))
54 *dst++ = *s++;
55 *dst = '\0';
56 return s;
59 static void cmd_page(struct mbox *mbox, char *args)
61 struct mail *mail;
62 pid_t pid;
63 int fds[2];
64 char num[MAXLINE];
65 int n = mbox->c;
66 args = cut_int(num, args);
67 if (isdigit(*num))
68 n = atoi(num);
69 if (n < 0 && n >= mbox->n)
70 return;
71 mail = &mbox->mails[n];
72 mbox->c = n;
73 pipe(fds);
74 if (!(pid = fork())) {
75 char *args[] = {PAGER, NULL};
76 close(fds[1]);
77 dup2(fds[0], STDIN_FILENO);
78 execvp(PAGER, args);
79 exit(1);
81 close(fds[0]);
82 write(fds[1], mail->head, mail->len);
83 close(fds[1]);
84 waitpid(pid, NULL, 0);
87 static char *cut_cmd(char *dst, char *s)
89 while (isalpha(*s)) {
90 *dst++ = *s++;
92 *dst = '\0';
93 return s;
96 static void cmd_head(struct mbox *mbox, char *args)
98 int i;
99 int n = MIN(mbox->n, 10);
100 for (i = 0; i < n; i++)
101 if (mbox->mails[i].subject)
102 till_eol(mbox->mails[i].subject);
105 static void loop(struct mbox *mbox)
107 char line[MAXLINE];
108 char cmd[MAXLINE];
109 while (read_line(line, sizeof(line)) > 0) {
110 char *args = cut_cmd(cmd, line);
111 int len = strlen(cmd);
112 if (!strncmp("header", cmd, len))
113 cmd_head(mbox, args);
114 if (!strncmp("page", cmd, len))
115 cmd_page(mbox, args);
116 if (!strncmp("quit", cmd, len))
117 return;
118 if (!strncmp("x", cmd, len) || !strncmp("exit", cmd, len))
119 return;
123 int main(int argc, char *argv[])
125 int i = 0;
126 struct mbox *mbox;
127 char *filename = NULL;
128 while (++i < argc)
129 if (!strcmp("-f", argv[i]))
130 filename = argv[++i];
131 if (filename) {
132 mbox = mbox_alloc(filename);
133 loop(mbox);
134 mbox_free(mbox);
136 return 0;