11 DIRCHUNK = 32*sizeof(Dir)
14 char regexchars[] = "\\/[].+?()*^$";
15 char deleted[] = "(deleted)-";
16 char deletedrx[] = "\\(deleted\\)-";
17 char deletedrx01[] = "(\\(deleted\\)-)?";
18 char deletedaddr[] = "-#0;/^\\(deleted\\)-/";
25 "text/", "edit", ".txt", /* must be first for plumbport() */
26 /* text must be first for plumbport() */
27 "image/gif", "image", ".gif",
28 "image/jpeg", "image", ".jpg",
29 "image/jpeg", "image", ".jpeg",
30 "image/png", "image", ".png",
31 "image/tiff", "image", ".tif",
32 "application/postscript", "postscript", ".ps",
33 "application/pdf", "postscript", ".pdf",
34 "application/msword", "msword", ".doc",
35 "application/rtf", "msword", ".rtf",
36 "audio/x-wav", "wav", ".wav",
45 "text/tab-separated-values",
46 "application/octet-stream",
69 char *extraheaders[] =
78 line(char *data, char **pp)
82 for(p=data; *p!='\0' && *p!='\n'; p++)
88 q = emalloc(p-data + 1);
89 memmove(q, data, p-data);
94 fc(Message *m, char *s)
99 r = smprint("%s <%s>", s, m->from);
105 return estrdup(m->from);
106 return estrdup("??");
110 loadinfo(Message *m, char *dir)
115 data = readfile(dir, "info", &n);
118 m->from = line(data, &p);
121 m->replyto = line(p, &p);
122 m->date = line(p, &p);
123 m->subject = line(p, &p);
124 m->type = line(p, &p);
125 m->disposition = line(p, &p);
126 m->filename = line(p, &p);
127 m->digest = line(p, &p);
128 /* m->bcc = */ free(line(p, &p));
129 /* m->inreplyto = */ free(line(p, &p));
130 /* m->date = */ free(line(p, &p));
131 /* m->sender = */ free(line(p, &p));
132 /* m->messageid = */ free(line(p, &p));
133 /* m->lines = */ free(line(p, &p));
134 /* m->size = */ free(line(p, &p));
135 /* m->flags = */ free(line(p, &p));
136 /* m->fileid = */ free(line(p, &p));
137 m->fromcolon = fc(m, line(p, &p));
155 loaddir(char *name, int *np)
160 fd = open(name, OREAD);
163 *np = dirreadall(fd, &dp);
169 readmbox(Message *mbox, char *dir, char *subdir)
175 name = estrstrdup(dir, subdir);
176 dirp = loaddir(name, &n);
181 if(isnumeric(d->name))
182 mesgadd(mbox, name, d, nil);
188 /* add message to box, in increasing numerical order */
190 mesgadd(Message *mbox, char *dir, Dir *d, char *digest)
196 m = emalloc(sizeof(Message));
197 m->name = estrstrdup(d->name, "/");
199 m->prev = mbox->tail;
200 m->level= mbox->level+1;
202 name = estrstrdup(dir, m->name);
203 loaded = loadinfo(m, name);
205 /* if two upas/fs are running, we can get misled, so check digest before accepting message */
206 if(loaded==0 || (digest!=nil && m->digest!=nil && strcmp(digest, m->digest)!=0)){
211 if(mbox->tail != nil)
212 mbox->tail->next = m;
214 if(mbox->head == nil)
219 readmbox(m, dir, m->name);
231 s = ctime(time(nil));
234 return strncmp(year, now, 4) == 0;
245 n = tokenize(s, fld, 10);
247 sprint(as, "%.3s ", fld[0]); /* day */
248 /* some dates have 19 Apr, some Apr 19 */
249 if(strlen(fld[1])<4 && isnumeric(fld[1]))
250 sprint(as+strlen(as), "%.3s %.3s ", fld[1], fld[2]); /* date, month */
252 sprint(as+strlen(as), "%.3s %.3s ", fld[2], fld[1]); /* date, month */
253 /* do we use time or year? depends on whether year matches this one */
254 if(thisyear(fld[5])){
255 if(strchr(fld[3], ':') != nil)
256 sprint(as+strlen(as), "%.5s ", fld[3]); /* time */
257 else if(strchr(fld[4], ':') != nil)
258 sprint(as+strlen(as), "%.5s ", fld[4]); /* time */
260 sprint(as+strlen(as), "%.4s ", fld[5]); /* year */
267 readfile(char *dir, char *name, int *np)
275 file = estrstrdup(dir, name);
276 fd = open(file, OREAD);
285 data = emalloc(len+1);
294 writefile(char *dir, char *name, char *s)
299 file = estrstrdup(dir, name);
300 // fprint(2, "writefile %s [%s]\n", file, s);
301 fd = open(file, OWRITE);
304 for(e = s + strlen(s); e - s > 0; s += n)
305 if((n = write(fd, s, e - s)) <= 0)
308 return s == e? 0: -1;
312 setflags(Message *m, char *f)
316 t = smprint("%s/%s", mbox.name, m->name);
317 writefile(t, "flags", f);
322 info(Message *m, int ind, int ogf)
334 if(ind==0 && altmenu){
338 if(ind==0 && m->subject[0]=='\0'){
339 snprint(fmt, sizeof fmt,
340 "\t%%-%d.%ds\t%%-12.12s\t", len, len);
341 snprint(s, sizeof s, fmt, p, stripdate(m->date) + 4);
343 snprint(fmt, sizeof fmt,
344 "\t%%-%d.%ds\t%%-12.12s\t%%-%d.%ds", len, len, lens, lens);
345 snprint(s, sizeof s, fmt, p, stripdate(m->date) + 4, m->subject);
352 if(ind==0 && shortmenu){
359 if(ind==0 && m->subject[0]=='\0'){
360 snprint(fmt, sizeof fmt, " %%-%d.%ds", len, len);
361 snprint(s, sizeof s, fmt, p);
363 snprint(fmt, sizeof fmt, " %%-%d.%ds %%-%d.%ds", len, len, lens, lens);
364 snprint(s, sizeof s, fmt, p, m->subject);
372 i = eappend(i, "\t", p);
373 i = egrow(i, "\t", stripdate(m->date));
375 if(strcmp(m->type, "text")!=0 && strncmp(m->type, "text/", 5)!=0 &&
376 strncmp(m->type, "multipart/", 10)!=0)
377 i = egrow(i, "\t(", estrstrdup(m->type, ")"));
378 }else if(strncmp(m->type, "multipart/", 10) != 0)
379 i = egrow(i, "\t(", estrstrdup(m->type, ")"));
380 if(m->subject[0] != '\0'){
381 i = eappend(i, "\n", nil);
383 i = eappend(i, "\t", nil);
384 i = eappend(i, "\t", m->subject);
390 mesgmenu0(Window *w, Message *mbox, char *realdir, char *dir, int ind, Biobuf *fd, int onlyone, int dotail)
397 if(strstr(realdir, "outgoing") != nil)
400 /* show mail box in reverse order, pieces in forward order */
410 name = estrstrdup(dir, m->name);
411 tmp = info(m, ind, ogf);
412 Bprint(fd, "%s%s\n", name, tmp);
414 if(dotail && m->tail)
415 mesgmenu0(w, m, realdir, name, ind+1, fd, 0, dotail);
427 mesgmenu(Window *w, Message *mbox)
429 winopenbody(w, OWRITE);
430 mesgmenu0(w, mbox, mbox->name, "", 0, w->body, 0, !shortmenu);
434 /* one new message has arrived, as mbox->tail */
436 mesgmenunew(Window *w, Message *mbox)
440 winselect(w, "0", 0);
441 w->data = winopenfile(w, "data");
442 b = emalloc(sizeof(Biobuf));
443 Binit(b, w->data, OWRITE);
444 mesgmenu0(w, mbox, mbox->name, "", 0, b, 1, !shortmenu);
449 /* select tag line plus following indented lines, but not final newline (it's distinctive) */
450 winselect(w, "0/.*\\n((\t.*\\n)*\t.*)?/", 1);
458 name2regexp(char *prefix, char *s)
462 buf = emalloc(strlen(prefix)+2*strlen(s)+50); /* leave room to append more */
469 for(q=s; *q!='\0'; q++){
470 if(strchr(regexchars, *q) != nil)
480 mesgmenumarkdel(Window *w, Message *mbox, Message *m, int writeback)
487 m->writebackdel = writeback;
489 w->data = winopenfile(w, "data");
490 buf = name2regexp("", m->name);
492 if(winselect(w, buf, 1))
493 write(w->data, deleted, 10);
497 w->addr = w->data = -1;
503 mesgmenumarkundel(Window *w, Message*, Message *m)
510 w->data = winopenfile(w, "data");
511 buf = name2regexp(deletedrx, m->name);
512 if(winselect(w, buf, 1))
513 if(winsetaddr(w, deletedaddr, 1))
514 write(w->data, "", 0);
518 w->addr = w->data = -1;
523 mesgmenudel(Window *w, Message *mbox, Message *m)
528 w->data = winopenfile(w, "data");
529 buf = name2regexp(deletedrx, m->name);
530 if(winsetaddr(w, buf, 1) && winsetaddr(w, ".,./.*\\n(\t.*\\n)*/", 1))
531 write(w->data, "", 0);
535 w->addr = w->data = -1;
541 mesgmenumark(Window *w, char *which, char *mark)
546 w->data = winopenfile(w, "data");
547 buf = name2regexp(deletedrx01, which);
548 if(winsetaddr(w, buf, 1) && winsetaddr(w, "+0-#1", 1)) /* go to end of line */
549 write(w->data, mark, strlen(mark));
553 w->addr = w->data = -1;
559 mesgfreeparts(Message *m)
571 free(m->disposition);
577 mesgdel(Message *mbox, Message *m)
582 error("internal error: deleted message still open in mesgdel");
583 /* delete subparts */
584 for(n=m->head; n!=nil; n=next){
588 /* remove this message from list */
590 m->next->prev = m->prev;
592 mbox->tail = m->prev;
594 m->prev->next = m->next;
596 mbox->head = m->next;
602 deliver(char *folder, char *file)
617 exec("/bin/upas/mbappend", av);
622 nz = !w->msg || !w->msg[0];
624 werrstr("%s", w->msg);
635 mesgsave(Message *m, char *s)
640 t = smprint("%s/%s/rawunix", mbox.name, m->name);
644 s = smprint("%s/%s", mailboxdir, s);
646 if(deliver(s, t) == -1){
647 fprint(2, "Mail: save failed: can't write %s: %r\n", s);
657 mesgcommand(Message *m, char *cmd)
665 nargs = tokenize(s, args, nelem(args));
668 if(strcmp(args[0], "Post") == 0){
672 if(strncmp(args[0], "Save", 4) == 0){
675 s = estrdup("\t[saved");
676 if(nargs==1 || strcmp(args[1], "")==0){
677 ok = mesgsave(m, "stored");
679 ok = mesgsave(m, args[1]);
680 s = eappend(s, " ", args[1]);
683 s = egrow(s, "]", nil);
684 mesgmenumark(mbox.w, m->name, s);
690 if(strcmp(args[0], "Reply")==0){
691 if(nargs>=2 && strcmp(args[1], "all")==0)
692 mkreply(m, "Replyall", nil, nil, nil);
694 mkreply(m, "Reply", nil, nil, nil);
698 if(strcmp(args[0], "Q") == 0){
699 s = winselection(m->w); /* will be freed by mkreply */
700 if(nargs>=3 && strcmp(args[1], "Reply")==0 && strcmp(args[2], "all")==0)
701 mkreply(m, "QReplyall", nil, nil, s);
703 mkreply(m, "QReply", nil, nil, s);
707 if(strcmp(args[0], "Del") == 0){
709 chanfree(m->w->cevent);
723 if(strcmp(args[0], "Delmesg") == 0){
725 mesgmenumarkdel(wbox, &mbox, m, 1);
726 free(cmd); /* mesgcommand might not return */
727 mesgcommand(m, estrdup("Del"));
733 if(strcmp(args[0], "UnDelmesg") == 0){
734 if(!m->isreply && m->deleted)
735 mesgmenumarkundel(wbox, &mbox, m);
736 // setflags(m, "-d");
739 // if(strcmp(args[0], "Headers") == 0){
752 mesgtagpost(Message *m)
756 wintagwrite(m->w, " Post", 5);
760 /* need to expand selection more than default word */
761 #pragma varargck argpos eval 2
764 eval(Window *w, char *s, ...)
770 vsnprint(buf, sizeof buf, s, arg);
773 if(winsetaddr(w, buf, 1)==0)
776 if(pread(w->addr, buf, 24, 0) != 24)
778 return strtol(buf, 0, 10);
790 else if(!isalpha(*s) && !isdigit(*s) && !strchr("_.-+/", *s))
795 char addrdelim[] = "/[ \t\\n<>()\\[\\]]/";
797 expandaddr(Window *w, Event *e)
802 if(e->q0 != e->q1) /* cannot happen */
805 q0 = eval(w, "#%d-%s", e->q0, addrdelim);
806 if(q0 == -1) /* bad char not found */
808 else /* increment past bad char */
811 q1 = eval(w, "#%d+%s", e->q0, addrdelim);
819 s = emalloc((q1-q0)*UTFmax+1);
820 winread(w, q0, q1, s);
825 replytoaddr(Window *w, Message *m, Event *e, char *s)
834 /* autoexpanded; use our own bigger expansion */
835 buf = expandaddr(w, e);
842 pm = emalloc(sizeof(Plumbmsg));
843 pm->src = estrdup("Mail");
844 pm->dst = estrdup("sendmail");
845 pm->data = estrdup(s);
847 if(m->subject && m->subject[0]){
848 pm->attr = emalloc(sizeof(Plumbattr));
849 pm->attr->name = estrdup("Subject");
850 if(tolower(m->subject[0]) != 'r' || tolower(m->subject[1]) != 'e' || m->subject[2] != ':')
851 pm->attr->value = estrstrdup("Re: ", m->subject);
853 pm->attr->value = estrdup(m->subject);
854 pm->attr->next = nil;
856 if(plumbsend(plumbsendfd, pm) < 0)
857 fprint(2, "error writing plumb message: %r\n");
870 Event *e, *eq, *e2, *ea;
872 char *os, *s, *t, *buf;
876 threadsetname("mesgctl");
877 proccreate(wineventproc, w, STACK);
879 e = recvp(w->cevent);
883 print("unknown message %c%c\n", e->c1, e->c2);
886 case 'E': /* write to body; can't affect us */
889 case 'F': /* generated by our actions; ignore */
892 case 'K': /* type away; we don't care */
895 case 'x': /* mouse only */
900 e2 = recvp(w->cevent);
904 ea = recvp(w->cevent);
909 if(eq->q1>eq->q0 && eq->nb==0){
910 s = emalloc((eq->q1-eq->q0)*UTFmax+1);
911 winread(w, eq->q0, eq->q1, s);
915 t = emalloc(strlen(s)+1+na+1);
916 sprint(t, "%s %s", s, ea->b);
920 if(!mesgcommand(m, s)) /* send it back */
924 case 'l': /* mouse only */
929 e2 = recvp(w->cevent);
933 if(eq->q1>eq->q0 && eq->nb==0){
934 buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
935 winread(w, eq->q0, eq->q1, buf);
941 /* skip mail box name if present */
942 if(strncmp(s, mbox.name, strlen(mbox.name)) == 0)
943 s += strlen(mbox.name);
944 if(strstr(s, "body") != nil){
945 /* strip any known extensions */
946 for(i=0; exts[i].ext!=nil; i++){
947 j = strlen(exts[i].ext);
948 if(strlen(s)>j && strcmp(s+strlen(s)-j, exts[i].ext)==0){
949 s[strlen(s)-j] = '\0';
953 if(strlen(s)>5 && strcmp(s+strlen(s)-5, "/body")==0)
954 s[strlen(s)-4] = '\0'; /* leave / in place */
956 nopen += mesgopen(&mbox, mbox.name, s, m, 0, nil);
957 while(*s!=0 && *s++!='\n')
960 if(nopen == 0 && e->c1 == 'L')
961 nopen += replytoaddr(w, m, e, os);
967 case 'I': /* modify away; we don't care */
983 mesgline(Message *m, char *header, char *value)
985 if(strlen(value) > 0)
986 Bprint(m->w->body, "%s: %s\n", header, value);
990 isprintable(char *type)
994 for(i=0; goodtypes[i]!=nil; i++)
995 if(strcmp(type, goodtypes[i])==0)
1005 for(i=0; exts[i].type!=nil; i++)
1006 if(strcmp(type, exts[i].type)==0)
1012 mimedisplay(Message *m, char *name, char *rootdir, Window *w, int fileonly)
1014 char *dest, *maildest;
1016 if(strcmp(m->disposition, "file")==0 || strlen(m->filename)!=0){
1017 if(strlen(m->filename) == 0){
1018 dest = estrdup(m->name);
1019 dest[strlen(dest)-1] = '\0';
1021 dest = estrdup(m->filename);
1022 if(maildest = getenv("maildest")){
1023 maildest = eappend(maildest, "/", dest);
1024 Bprint(w->body, "\tcp %s%sbody%s %q\n", rootdir, name, ext(m->type), maildest);
1027 if(m->filename[0] != '/')
1028 dest = egrow(estrdup(home), "/", dest);
1029 Bprint(w->body, "\tcp %s%sbody%s %q\n", rootdir, name, ext(m->type), dest);
1032 Bprint(w->body, "\tfile is %s%sbody%s\n", rootdir, name, ext(m->type));
1036 printheader(char *dir, Biobuf *b, char **okheaders)
1042 s = readfile(dir, "header", nil);
1045 n = getfields(s, lines, nelem(lines), 0, "\n");
1047 for(j=0; okheaders[j]; j++)
1048 if(cistrncmp(lines[i], okheaders[j], strlen(okheaders[j])) == 0)
1049 Bprint(b, "%s\n", lines[i]);
1054 mesgload(Message *m, char *rootdir, char *file, Window *w)
1056 char *s, *subdir, *name, *dir;
1057 Message *mp, *thisone;
1060 dir = estrstrdup(rootdir, file);
1062 if(strcmp(m->type, "message/rfc822") != 0){ /* suppress headers of envelopes */
1063 if(strlen(m->from) > 0){
1064 Bprint(w->body, "From: %s\n", m->from);
1065 mesgline(m, "Date", m->date);
1066 mesgline(m, "To", m->to);
1067 mesgline(m, "CC", m->cc);
1068 mesgline(m, "Subject", m->subject);
1069 printheader(dir, w->body, extraheaders);
1071 printheader(dir, w->body, okheaders);
1072 printheader(dir, w->body, extraheaders);
1074 Bprint(w->body, "\n");
1077 if(m->level == 1 && m->recursed == 0){
1079 readmbox(m, rootdir, m->name);
1081 if(m->head == nil){ /* single part message */
1082 if(strcmp(m->type, "text")==0 || strncmp(m->type, "text/", 5)==0){
1083 mimedisplay(m, m->name, rootdir, w, 1);
1084 s = readbody(m->type, dir, &n);
1085 winwritebody(w, s, n);
1088 mimedisplay(m, m->name, rootdir, w, 0);
1090 /* multi-part message, either multipart/* or message/rfc822 */
1092 if(strcmp(m->type, "multipart/alternative") == 0){
1093 thisone = m->head; /* in case we can't find a good one */
1094 for(mp=m->head; mp!=nil; mp=mp->next)
1095 if(isprintable(mp->type)){
1100 for(mp=m->head; mp!=nil; mp=mp->next){
1101 if(thisone!=nil && mp!=thisone)
1103 subdir = estrstrdup(dir, mp->name);
1104 name = estrstrdup(file, mp->name);
1105 /* skip first element in name because it's already in window name */
1107 Bprint(w->body, "\n===> %s (%s) [%s]\n", strchr(name, '/')+1, mp->type, mp->disposition);
1108 if(strcmp(mp->type, "text")==0 || strncmp(mp->type, "text/", 5)==0){
1109 mimedisplay(mp, name, rootdir, w, 1);
1110 printheader(subdir, w->body, okheaders);
1111 printheader(subdir, w->body, extraheaders);
1112 winwritebody(w, "\n", 1);
1113 s = readbody(mp->type, subdir, &n);
1114 winwritebody(w, s, n);
1117 if(strncmp(mp->type, "multipart/", 10)==0 || strcmp(mp->type, "message/rfc822")==0){
1119 mesgload(mp, rootdir, name, w);
1122 mimedisplay(mp, name, rootdir, w, 0);
1132 tokenizec(char *str, char **args, int max, char *splitc)
1139 for(na=0; *str != '\0';str++){
1140 if(strchr(splitc, *str) == nil){
1146 /* it's a separator/skip character */
1159 mesglookup(Message *mbox, char *name, char *digest)
1166 /* can find exactly */
1167 for(m=mbox->head; m!=nil; m=m->next)
1168 if(strcmp(digest, m->digest) == 0)
1176 if(name[n-1] == '/')
1179 t = estrstrdup(name, "/");
1180 for(m=mbox->head; m!=nil; m=m->next)
1181 if(strcmp(t, m->name) == 0)
1188 * Find plumb port, knowing type is text, given file name (by extension)
1191 plumbportbysuffix(char *file)
1196 nfile = strlen(file);
1197 for(i=0; ports[i].type!=nil; i++){
1198 suf = ports[i].suffix;
1201 if(cistrncmp(file+nfile-nsuf, suf, nsuf) == 0)
1208 * Find plumb port using type and file name (by extension)
1211 plumbport(char *type, char *file)
1215 for(i=0; ports[i].type!=nil; i++)
1216 if(strncmp(type, ports[i].type, strlen(ports[i].type)) == 0)
1218 /* see if it's a text type */
1219 for(i=0; goodtypes[i]!=nil; i++)
1220 if(strncmp(type, goodtypes[i], strlen(goodtypes[i])) == 0)
1221 return plumbportbysuffix(file);
1226 plumb(Message *m, char *dir)
1232 if(strlen(m->type) == 0)
1234 i = plumbport(m->type, m->filename);
1236 fprint(2, "can't find destination for message subpart\n");
1238 port = ports[i].port;
1239 pm = emalloc(sizeof(Plumbmsg));
1240 pm->src = estrdup("Mail");
1242 pm->dst = estrdup(port);
1246 pm->type = estrdup("text");
1248 pm->data = estrstrdup(dir, "body");
1249 pm->data = eappend(pm->data, "", ports[i].suffix);
1250 if(plumbsend(plumbsendfd, pm) < 0)
1251 fprint(2, "error writing plumb message: %r\n");
1257 mesgopen(Message *mbox, char *dir, char *s, Message *mesg, int plumbed, char *digest)
1262 int i, ndirelem, reuse;
1264 /* find white-space-delimited first word */
1265 for(t=s; *t!='\0' && !isspace(*t); t++)
1269 /* separate it on slashes */
1270 ndirelem = tokenizec(u, direlem, nelem(direlem), "/");
1277 write(wctlfd, "top", 3);
1278 write(wctlfd, "current", 7);
1280 /* open window for message */
1281 m = mesglookup(mbox, direlem[0], digest);
1284 if(mesg!=nil && m!=mesg) /* string looked like subpart but isn't part of this message */
1292 /* re-use existing window */
1293 if(winsetaddr(m->w, "0,$", 1)){
1295 m->w->data = winopenfile(m->w, "data");
1296 write(m->w->data, "", 0);
1299 v = estrstrdup(mbox->name, m->name);
1304 wintagwrite(m->w, "Q Reply all UnDelmesg Save ", 2+6+4+10+5);
1306 wintagwrite(m->w, "Q Reply all Delmesg Save ", 2+6+4+8+5);
1308 threadcreate(mesgctl, m, STACK);
1309 winopenbody(m->w, OWRITE);
1310 mesgload(m, dir, m->name, m->w);
1320 if(ndirelem == 1 && plumbport(m->type, m->filename) <= 0){
1321 /* make sure dot is visible */
1322 ctlprint(m->w->ctl, "show\n");
1325 /* walk to subpart */
1326 dir = estrstrdup(dir, m->name);
1327 for(i=1; i<ndirelem; i++){
1328 m = mesglookup(m, direlem[i], digest);
1331 dir = egrow(dir, m->name, nil);
1333 if(m != nil && plumbport(m->type, m->filename) > 0)
1341 rewritembox(Window *w, Message *mbox)
1344 char *deletestr, *t;
1347 deletestr = estrstrdup("delete ", fsname);
1350 for(m=mbox->head; m!=nil; m=next){
1358 if(m->writebackdel){
1359 /* messages deleted by plumb message are not removed again */
1360 t = estrdup(m->name);
1362 t[strlen(t)-1] = '\0';
1363 deletestr = egrow(deletestr, " ", t);
1365 mesgmenudel(w, mbox, m);
1368 if(write(mbox->ctlfd, deletestr, strlen(deletestr)) < 0)
1369 fprint(2, "Mail: warning: error removing mail message files: %r\n");
1371 winselect(w, "0", 0);
1377 /* name is a full file name, but it might not belong to us */
1379 mesglookupfile(Message *mbox, char *name, char *digest)
1384 n = strlen(mbox->name);
1385 if(k==0 || strncmp(name, mbox->name, n) != 0){
1386 // fprint(2, "Mail: message %s not in this mailbox\n", name);
1389 return mesglookup(mbox, name+n, digest);