/* mdfrm.c -- mdfrm(1) for maildir. * * $Id$ * * This program is in the public domain. */ #include #include #include #include #include #include #include #include #include /* Note that PATH_MAX is supposed to include the terminating null. */ #ifndef PATH_MAX #ifndef MAXPATHLEN #define PATH_MAX 65 #else #define PATH_MAX MAXPATHLEN #endif #endif enum { FROMLEN = 5, /* "From:" */ SUBJLEN = 8, /* "Subject:" */ /* Number of characters for each field we actually output. This * must also be changed in the printf functions at the end of the * frm function. */ FROMCOUNT = 24, SUBJCOUNT = 53 }; static char ident[] = "$Id$"; static void err(int exitcode, char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); perror(" "); exit(exitcode); } static void errx(int exitcode, char *format, ...) { va_list ap; va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fputs("\n", stderr); exit(exitcode); } static void sanitize(char *str, size_t len) { int i; for (i = 0; i < len; i++) { if (isprint(str[i]) == 0) { str[i] = '?'; } } } static void scan_message(char *filename, char *fromheader, char *subjheader) { FILE *file; char *line; size_t len, fromcount, subjcount; if (!(file = fopen(filename, "r"))) { err(EX_OSERR, "Failed fopen(%s)", filename); } fromcount = subjcount = 0; fromheader[0] = subjheader[0] = '\0'; while ((line = fgetln(file, &len))) { if (len <= 1) { break; } --len; if (len > FROMLEN && strncasecmp(line, "From:", FROMLEN) == 0) { line += FROMLEN; len -= FROMLEN; while (len > 0 && isspace(line[0])) { line++; len--; } if (len < FROMCOUNT) { fromcount = len; } else { fromcount = FROMCOUNT; } strncpy(fromheader, line, fromcount); fromheader[fromcount] = '\0'; sanitize(fromheader, fromcount); } else if (len > SUBJLEN && strncasecmp(line, "Subject:", SUBJLEN) == 0) { line += SUBJLEN; len -= SUBJLEN; while (len > 0 && isspace(line[0])) { line++; len--; } if (len < SUBJCOUNT) { subjcount = len; } else { subjcount = SUBJCOUNT; } strncpy(subjheader, line, subjcount); subjheader[subjcount] = '\0'; sanitize(subjheader, subjcount); } } fclose(file); } static void frm(char *dirname, int showfn) { DIR *dir; struct dirent *dirent; char *filename; char fromheader[FROMCOUNT + 1] = { '\0' }; char subjheader[SUBJCOUNT + 1] = { '\0' }; if (chdir(dirname) != 0) { err(EX_OSERR, "Failed chdir(%s)", dirname); } if (chdir("new") != 0) { err(EX_OSERR, "Failed chdir(%s/new)", dirname); } dir = opendir("."); if (!dir) { err(EX_OSERR, "Failed opendir(%s/new)", dirname); } for (dirent = readdir(dir); dirent; dirent = readdir(dir)) { filename = dirent->d_name; if (filename[0] == '.') { continue; } scan_message(filename, fromheader, subjheader); if (showfn) { printf("%s ", filename); } printf("%-24s ", fromheader); printf("%s\n", subjheader); } } int main(int argc, char *argv[]) { char *dirname; char buf[PATH_MAX]; int showfn = 0; if (argv[1] && argv[1][0] == '-' && argv[1][1] == 'v') { puts(ident); return 0; } if (argv[1] && argv[1][0] == '-' && argv[1][1] == 'f') { showfn = 1; argv++; } if (!(dirname = argv[1])) { if (!(dirname = getenv("MAILDIR"))) { if (!(dirname = getenv("HOME"))) { errx(EX_UNAVAILABLE, "Could not find maildir."); } else { snprintf(buf, PATH_MAX, "%s/Maildir", dirname); dirname = buf; } } } frm(dirname, showfn); return 0; }