2 * Another stupid program, this one parsing the headers of an
3 * email to figure out authorship and subject
10 static FILE *cmitmsg, *patchfile;
12 static int keep_subject = 0;
13 static char line[1000];
14 static char date[1000];
15 static char name[1000];
16 static char email[1000];
17 static char subject[1000];
19 static char *sanity_check(char *name, char *email)
21 int len = strlen(name);
22 if (len < 3 || len > 60)
24 if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>'))
29 static int handle_from(char *line)
31 char *at = strchr(line, '@');
38 * If we already have one email, don't take any confusing lines
40 if (*email && strchr(at+1, '@'))
45 if (isspace(c) || c == '<')
51 unsigned char c = *at;
52 if (!c || c == '>' || isspace(c))
59 at = line + strlen(line);
61 unsigned char c = *--at;
69 unsigned char c = *at;
77 at = sanity_check(at, email);
83 static void handle_date(char *line)
88 static void handle_subject(char *line)
90 strcpy(subject, line);
93 static void check_line(char *line, int len)
95 if (!memcmp(line, "From:", 5) && isspace(line[5]))
97 else if (!memcmp(line, "Date:", 5) && isspace(line[5]))
99 else if (!memcmp(line, "Subject:", 8) && isspace(line[8]))
100 handle_subject(line+9);
103 static char * cleanup_subject(char *subject)
112 if (!memcmp("e:", subject+1, 2)) {
117 case ' ': case '\t': case ':':
122 p = strchr(subject, ']');
128 remove = p - subject;
129 if (remove <= len *2) {
139 static void cleanup_space(char *buf)
142 while ((c = *buf) != 0) {
148 int len = strlen(buf);
149 memmove(buf, buf+1, len);
156 static void handle_rest(void)
159 char *sub = cleanup_subject(subject);
162 cleanup_space(email);
164 printf("Author: %s\nEmail: %s\nSubject: %s\nDate: %s\n\n", name, email, sub, date);
167 if (!memcmp("diff -", line, 6) ||
168 !memcmp("---", line, 3) ||
169 !memcmp("Index: ", line, 7))
173 } while (fgets(line, sizeof(line), stdin) != NULL);
175 if (out == cmitmsg) {
176 fprintf(stderr, "No patch found\n");
184 static int eatspace(char *line)
186 int len = strlen(line);
187 while (len > 0 && isspace(line[len-1]))
192 static void handle_body(void)
197 /* First lines of body can have From: and Date: */
198 while (fgets(line, sizeof(line), stdin) != NULL) {
199 int len = eatspace(line);
202 if (!memcmp("From:", line, 5) && isspace(line[5])) {
203 if (!has_from && handle_from(line+6)) {
208 if (!memcmp("Date:", line, 5) && isspace(line[5])) {
221 static int read_one_header_line(char *line, int sz, FILE *in)
226 if (fgets(line + ofs, sz - ofs, in) == NULL)
228 len = eatspace(line + ofs);
231 peek = fgetc(in); ungetc(peek, in);
232 if (peek == ' ' || peek == '\t') {
233 /* Yuck, 2822 header "folding" */
242 static void usage(void)
244 fprintf(stderr, "mailinfo msg-file patch-file < email\n");
248 static const char mailinfo_usage[] =
249 "git-mailinfo [-k] msg patch <mail >info";
250 int main(int argc, char ** argv)
252 while (1 < argc && argv[1][0] == '-') {
253 if (!strcmp(argv[1], "-k"))
256 fprintf(stderr, "usage: %s\n", mailinfo_usage);
264 cmitmsg = fopen(argv[1], "w");
269 patchfile = fopen(argv[2], "w");
275 int len = read_one_header_line(line, sizeof(line), stdin);
280 check_line(line, len);