ex: escaped characters in global command pattern
[neatmail.git] / mk.c
blob3fec751c9ecf7f6ef4d0b977e824fabba5c5497e
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "mail.h"
7 static int uc_len(char *s)
9 int c = (unsigned char) s[0];
10 if (~c & 0x80)
11 return c > 0;
12 if (~c & 0x20)
13 return 2;
14 if (~c & 0x10)
15 return 3;
16 if (~c & 0x80)
17 return 4;
18 if (~c & 0x40)
19 return 5;
20 if (~c & 0x20)
21 return 6;
22 return 1;
25 static int uc_wid(char *s)
27 return 1;
30 static char *msg_dec(char *msg, long msz, char *hdr)
32 char *val = msg_get(msg, msz, hdr);
33 char *buf, *ret;
34 int val_len;
35 if (!val)
36 return NULL;
37 val_len = hdrlen(val, msg + msz - val) - 1;
38 buf = malloc(val_len + 1);
39 memcpy(buf, val, val_len);
40 buf[val_len] = '\0';
41 ret = msg_hdrdec(buf);
42 free(buf);
43 return ret;
46 static int msg_stat(char *msg, long msz)
48 char *val = msg_get(msg, msz, "status:");
49 if (!val)
50 return 'N';
51 val += strlen("status:");
52 while (isspace((unsigned char) val[0]))
53 val++;
54 return val[0];
57 static char *fieldformat(char *msg, long msz, char *hdr, int wid)
59 struct sbuf *dst;
60 int dst_wid;
61 char *val = msg_dec(msg, msz, hdr);
62 char *val0, *end;
63 if (!val) {
64 val = malloc(1);
65 val[0] = '\0';
67 val0 = val;
68 end = strchr(val, '\0');
69 dst = sbuf_make();
70 val += strlen(hdr);
71 while (val < end && isspace((unsigned char) *val))
72 val++;
73 dst_wid = 0;
74 while (val < end && (wid <= 0 || dst_wid < wid)) {
75 int l = uc_len(val);
76 if (l == 1) {
77 int c = (unsigned char) *val;
78 sbuf_chr(dst, isblank(c) || !isprint(c) ? ' ' : c);
79 } else {
80 sbuf_mem(dst, val, l);
82 dst_wid += uc_wid(val);
83 val += l;
85 if (wid > 0)
86 while (dst_wid++ < wid)
87 sbuf_chr(dst, ' ');
88 free(val0);
89 return sbuf_done(dst);
92 static char *segment(char *d, char *s, int m)
94 char *r = strchr(s, m);
95 char *e = r ? r + 1 : strchr(s, '\0');
96 memcpy(d, s, e - s);
97 d[e - s] = '\0';
98 return e;
101 static char *usage =
102 "usage: neatmail mk [options] mbox\n\n"
103 "options:\n"
104 " -0 fmt \tmessage first line format (e.g., 20from:40subject:)\n"
105 " -1 fmt \tmessage second line format\n"
106 " -f n \tthe first message to list\n";
108 int mk(char *argv[])
110 struct mbox *mbox;
111 char *ln[4] = {NULL};
112 int i, j;
113 int first = 0;
114 for (i = 0; argv[i] && argv[i][0] == '-'; i++) {
115 if (argv[i][1] == 'f') {
116 first = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
117 continue;
119 if (argv[i][1] == '0' || argv[i][1] == '1') {
120 int idx = argv[i][1] - '0';
121 ln[idx] = argv[i][2] ? argv[i] + 2 : argv[++i];
122 continue;
125 if (!argv[i]) {
126 printf("%s", usage);
127 return 1;
129 mbox = mbox_open(argv[i]);
130 if (!mbox) {
131 fprintf(stderr, "neatmail: cannot open <%s>\n", argv[i]);
132 return 1;
134 for (i = first; i < mbox_len(mbox); i++) {
135 char *msg;
136 long msz;
137 mbox_get(mbox, i, &msg, &msz);
138 printf("%c%04d", msg_stat(msg, msz), i);
139 for (j = 0; ln[j]; j++) {
140 char *cln = ln[j];
141 char *tok = malloc(strlen(ln[j]) + 1);
142 if (j)
143 printf("\n");
144 while ((cln = segment(tok, cln, ':')) && tok[0]) {
145 char *fmt = tok;
146 char *hdr = tok;
147 char *val;
148 while (isdigit((unsigned char) *hdr))
149 hdr++;
150 val = fieldformat(msg, msz, hdr, atoi(fmt));
151 printf("\t%s", val);
152 free(val);
154 free(tok);
156 printf("\n");
158 mbox_free(mbox);
159 return 0;