#!/usr/local/bin/pike -w #pragma strict_types class Mbox_iterator { static { constant BSIZE = 8192; Stdio.Stream f; int which; string current; string buf = ""; // read-ahead into the stream } static int(0..1) find_next() { int offset; /* find the beginning, usually we're already there.. */ while((offset=search(buf, "\n\nFrom "))==-1) { string tmp = f->read(BSIZE); if(!sizeof(tmp)) { current = ""; return 0; } buf += tmp; } buf = buf[offset..]; /* ..then the end */ while((offset=search(buf, "\n\nFrom ", 7))==-1) { string tmp = f->read(BSIZE); if(!sizeof(tmp)) { current = buf[2..]; // snip leading newlines buf = ""; return 1; } else { buf += tmp; } } current = buf[2..offset-1]; // snip leading newlines buf = buf[offset..]; return 1; } int index() { return which; } string value() { return current; } int(0..1) `!() // return 1 if the iterator is 'done' { return !sizeof(current); } #if 0 Mbox_iterator `+(int(0..) nsteps) { error("Mbox_iterator.`+(): not implemented.\n"); } #endif Mbox_iterator `+=(int(0..) nsteps) { while(nsteps--) next(); return this_object(); } int(0..1) next() // like `+=(1), but return 0 if the iterator is finished { return find_next() ? (++which, 1) : 0; } int(0..1) first() // restart, return 0 if it fails { return 0; } static void create(Stdio.Stream _f) { f = _f; buf = f->read(BSIZE); if(buf[..4]!="From ") { find_next(); return; } else // beginning is OK, find end { int offset; while((offset=search(buf,"\n\nFrom ", 5))==-1) { string tmp = f->read(BSIZE); if(!sizeof(tmp)) { current = buf; // no leading newlines here buf = ""; return; } else { buf += tmp; } } current = buf[..offset-1]; // no leading newlines here buf = buf[offset..]; return; } } } int main(int ac, array(string) av) { Stdio.Stream mbox; array(array(string)) header_data = ({}); if(ac>1) { if(av[1]=="-") mbox = Stdio.stdin; else mbox = Stdio.File(av[1], "r"); } else { string mpath = (string)(getenv("MAIL") || ("/var/mail/" + ( getenv("USER") || getenv("LOGNAME")))); mbox = Stdio.File(mpath, "r"); } Mbox_iterator it = Mbox_iterator(mbox); while(!!it) { header_data += ({ ({ (string)(it->index()+1) }) + headers(it->value()) }); it->next(); } int cols = [int](Stdio.stderr->tcgetattr()->columns) || 80; string format = "%{%-3s %!-"+(string)((cols-6)*2/5)+"s %!-"+(string)((cols-6)*3/5)+ "s\n%}"; write(format, header_data); return 0; } array(string) headers(string current) { array(string) res = ({"",""}); array(string) tmp = current/"\n\n"; if(tmp[0] == "") { current=tmp[1]; } else if(tmp[0][..4]=="From ") { current = tmp[0]; } else error("headers(): unexpected malformed argument."); foreach(current/"\n", string line) { if(lower_case(line[..4])=="from:") { res[0] = line[5..]; } else if(lower_case(line[..7])=="subject:") { res[1] = line[8..]; } } return res; }