]> diplodocus.org Git - mdfrm/blob - mdfrm.c
9ab6207c62d5b1dbc249e16bc0b19f6ab7e782c0
[mdfrm] / mdfrm.c
1 /* mdfrm.c -- mdfrm(1) for maildir.
2 *
3 * $Id$
4 *
5 * This program is in the public domain.
6 */
7
8 #include <sys/types.h>
9
10 #include <ctype.h>
11 #include <dirent.h>
12 #include <err.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sysexits.h>
17 #include <unistd.h>
18
19 /* Note that PATH_MAX is supposed to include the terminating null. */
20 #ifndef PATH_MAX
21 #ifndef MAXPATHLEN
22 #define PATH_MAX 65
23 #else
24 #define PATH_MAX MAXPATHLEN
25 #endif
26 #endif
27
28 enum {
29 FROMLEN = 5, /* "From:" */
30 SUBJLEN = 8, /* "Subject:" */
31
32 /* Number of characters for each field we actually output. This
33 * must also be changed in the printf functions at the end of the
34 * frm function.
35 */
36 FROMCOUNT = 24,
37 SUBJCOUNT = 53
38 };
39
40 static char ident[] = "$Id$";
41
42 static void
43 sanitize(char *str, size_t len)
44 {
45 int i;
46
47 for (i = 0; i < len; i++) {
48 if (iscntrl(str[i])) {
49 str[i] = '?';
50 }
51 }
52 }
53
54 static void
55 scan_message(char *filename, char *fromheader, char *subjheader)
56 {
57 FILE *file;
58 char *line;
59 size_t len, fromcount, subjcount;
60
61 if (!(file = fopen(filename, "r"))) {
62 err(EX_OSERR, "Failed fopen(%s)", filename);
63 }
64
65 fromcount = subjcount = 0;
66 fromheader[0] = subjheader[0] = '\0';
67 while ((line = fgetln(file, &len))) {
68 if (len <= 1) {
69 break;
70 }
71 --len;
72
73 if (len > FROMLEN && strncasecmp(line, "From:", FROMLEN) == 0) {
74 line += FROMLEN;
75 len -= FROMLEN;
76 while (len > 0 && isspace(line[0])) {
77 line++;
78 len--;
79 }
80 if (len < FROMCOUNT) {
81 fromcount = len;
82 } else {
83 fromcount = FROMCOUNT;
84 }
85 strncpy(fromheader, line, fromcount);
86 fromheader[fromcount] = '\0';
87 sanitize(fromheader, fromcount);
88 } else if (len > SUBJLEN && strncasecmp(line, "Subject:", SUBJLEN) == 0) {
89 line += SUBJLEN;
90 len -= SUBJLEN;
91 while (len > 0 && isspace(line[0])) {
92 line++;
93 len--;
94 }
95 if (len < SUBJCOUNT) {
96 subjcount = len;
97 } else {
98 subjcount = SUBJCOUNT;
99 }
100 strncpy(subjheader, line, subjcount);
101 subjheader[subjcount] = '\0';
102 sanitize(subjheader, subjcount);
103 }
104 }
105
106 fclose(file);
107 }
108
109 static void
110 frm(char *dirname, int showfn)
111 {
112 DIR *dir;
113 struct dirent *dirent;
114 char *filename;
115 char fromheader[FROMCOUNT + 1] = { '\0' };
116 char subjheader[SUBJCOUNT + 1] = { '\0' };
117
118 if (chdir(dirname) != 0) {
119 err(EX_OSERR, "Failed chdir(%s)", dirname);
120 }
121
122 if (chdir("new") != 0) {
123 err(EX_OSERR, "Failed chdir(%s/new)", dirname);
124 }
125
126 dir = opendir(".");
127 if (!dir) {
128 err(EX_OSERR, "Failed opendir(%s/new)", dirname);
129 }
130
131 for (dirent = readdir(dir); dirent; dirent = readdir(dir)) {
132 filename = dirent->d_name;
133 if (filename[0] == '.') {
134 continue;
135 }
136
137 scan_message(filename, fromheader, subjheader);
138
139 if (showfn) {
140 printf("%s: ", filename);
141 }
142 printf("%-24s ", fromheader);
143 printf("%s\n", subjheader);
144 }
145 }
146
147 int
148 main(int argc, char *argv[])
149 {
150 char *dirname;
151 char buf[PATH_MAX];
152 int showfn = 0;
153
154 if (argv[1] && argv[1][0] == '-' && argv[1][1] == 'v') {
155 puts(ident);
156 return 0;
157 }
158
159 if (argv[1] && argv[1][0] == '-' && argv[1][1] == 'f') {
160 showfn = 1;
161 argv++;
162 }
163
164 if (!(dirname = argv[1])) {
165 if (!(dirname = getenv("MAILDIR"))) {
166 if (!(dirname = getenv("HOME"))) {
167 errx(EX_UNAVAILABLE, "Could not find maildir.");
168 } else {
169 snprintf(buf, PATH_MAX, "%s/Maildir", dirname);
170 dirname = buf;
171 }
172 }
173 }
174
175 frm(dirname, showfn);
176
177 return 0;
178 }