/* add message to box, in increasing numerical order */ int mesgadd(Message *mbox, char *dir, Dir *d, char *digest) { Message *m; char *name; int loaded; m = emalloc(sizeof(Message)); m->name = estrstrdup(d->name, "/"); m->next = nil; m->prev = mbox->tail; m->level= mbox->level+1; m->recursed = 0; name = estrstrdup(dir, m->name); loaded = loadinfo(m, name); free(name); /* if two upas/fs are running, we can get misled, so check digest before accepting message */ if(loaded==0 || (digest!=nil && m->digest!=nil && strcmp(digest, m->digest)!=0)){ mesgfreeparts(m); free(m); return 0; } if(mbox->tail != nil) mbox->tail->next = m; mbox->tail = m; if(mbox->head == nil) mbox->head = m; if (m->level != 1){ m->recursed = 1; readmbox(m, dir, m->name); } return 1; }
void main(int argc, char **argv) { char *err; char *mboxfile; ARGBEGIN{ }ARGEND; if(argc > 0) mboxfile = argv[0]; else mboxfile = "./mbox"; root = newmessage(nil); err = readmbox(mboxfile, &root->part); if(err != nil){ fprint(2, "boom: %s\n", err); exits(0); } info(0, 1, root); exits(0); }
static int dologin(char *response) { AuthInfo *ai; static int tries; static uint32_t delaysecs = 5; chs->user = user; chs->resp = response; chs->nresp = strlen(response); if((ai = auth_response(chs)) == nil){ if(tries >= 20){ senderr("authentication failed: %r; server exiting"); exits(nil); } if(++tries == 3) syslog(0, "pop3", "likely password guesser from %s", peeraddr); delaysecs *= 2; if (delaysecs > 30*60) delaysecs = 30*60; /* half-hour max. */ sleep(delaysecs * 1000); /* prevent beating on our auth server */ return senderr("authentication failed"); } if(auth_chuid(ai, nil) < 0){ senderr("chuid failed: %r; server exiting"); exits(nil); } auth_freeAI(ai); auth_freechal(chs); chs = nil; loggedin = 1; if(newns(user, 0) < 0){ senderr("newns failed: %r; server exiting"); exits(nil); } syslog(0, "pop3", "user %s logged in", user); enableaddr(); if(readmbox(box) < 0) exits(nil); return sendok("mailbox is %s", box); }
void mesgload(Message *m, char *rootdir, char *file, Window *w) { char *s, *subdir, *name, *dir; Message *mp, *thisone; int n; dir = estrstrdup(rootdir, file); if(strcmp(m->type, "message/rfc822") != 0){ /* suppress headers of envelopes */ if(strlen(m->from) > 0){ Bprint(w->body, "From: %s\n", m->from); mesgline(m, "Date", m->date); mesgline(m, "To", m->to); mesgline(m, "CC", m->cc); mesgline(m, "Subject", m->subject); printheader(dir, w->body, extraheaders); }else{ printheader(dir, w->body, okheaders); printheader(dir, w->body, extraheaders); } Bprint(w->body, "\n"); } if(m->level == 1 && m->recursed == 0){ m->recursed = 1; readmbox(m, rootdir, m->name); } if(m->head == nil){ /* single part message */ if(strcmp(m->type, "text")==0 || strncmp(m->type, "text/", 5)==0){ mimedisplay(m, m->name, rootdir, w, 1); s = readbody(m->type, dir, &n); winwritebody(w, s, n); free(s); }else mimedisplay(m, m->name, rootdir, w, 0); }else{ /* multi-part message, either multipart or message/rfc822 */ thisone = nil; if(strcmp(m->type, "multipart/alternative") == 0){ thisone = bestalt(m, dir); if(thisone == nil){ thisone = m->head; /* in case we can't find a good one */ for(mp=m->head; mp!=nil; mp=mp->next) if(isprintable(mp->type)){ thisone = mp; break; } } } for(mp=m->head; mp!=nil; mp=mp->next){ if(thisone!=nil && mp!=thisone) continue; subdir = estrstrdup(dir, mp->name); name = estrstrdup(file, mp->name); /* skip first element in name because it's already in window name */ if(mp != m->head) Bprint(w->body, "\n===> %s (%s) [%s]\n", strchr(name, '/')+1, mp->type, mp->disposition); if(strcmp(mp->type, "text")==0 || strncmp(mp->type, "text/", 5)==0){ mimedisplay(mp, name, rootdir, w, 1); printheader(subdir, w->body, okheaders); printheader(subdir, w->body, extraheaders); winwritebody(w, "\n", 1); s = readbody(mp->type, subdir, &n); winwritebody(w, s, n); free(s); }else{ if(strncmp(mp->type, "multipart/", 10)==0 || strcmp(mp->type, "message/rfc822")==0){ mp->w = w; mesgload(mp, rootdir, name, w); mp->w = nil; }else mimedisplay(mp, name, rootdir, w, 0); } free(name); free(subdir); } } free(dir); }
void threadmain(int argc, char *argv[]) { char *s, *name; char err[ERRMAX], *cmd; int i, newdir; Fmt fmt; doquote = needsrcquote; quotefmtinstall(); /* open these early so we won't miss notification of new mail messages while we read mbox */ if((plumbsendfd = plumbopenfid("send", OWRITE|OCEXEC)) == nil) fprint(2, "warning: open plumb/send: %r\n"); if((plumbseemailfd = plumbopenfid("seemail", OREAD|OCEXEC)) == nil) fprint(2, "warning: open plumb/seemail: %r\n"); if((plumbshowmailfd = plumbopenfid("showmail", OREAD|OCEXEC)) == nil) fprint(2, "warning: open plumb/showmail: %r\n"); shortmenu = 0; srvname = "mail"; ARGBEGIN{ case 's': shortmenu = 1; break; case 'S': shortmenu = 2; break; case 'o': outgoing = EARGF(usage()); break; case 'm': smprint(maildir, "%s/", EARGF(usage())); break; case 'n': srvname = EARGF(usage()); break; default: usage(); }ARGEND acmefs = nsmount("acme",nil); if(acmefs == nil) error("cannot mount acme: %r"); mailfs = nsmount(srvname, nil); if(mailfs == nil) error("cannot mount %s: %r", srvname); name = "mbox"; newdir = 1; if(argc > 0){ i = strlen(argv[0]); if(argc>2 || i==0) usage(); /* see if the name is that of an existing /mail/fs directory */ if(argc==1 && argv[0][0] != '/' && ismaildir(argv[0])){ name = argv[0]; mboxname = estrdup(name); newdir = 0; }else{ if(argv[0][i-1] == '/') argv[0][i-1] = '\0'; s = strrchr(argv[0], '/'); if(s == nil) mboxname = estrdup(argv[0]); else{ *s++ = '\0'; if(*s == '\0') usage(); mailboxdir = argv[0]; mboxname = estrdup(s); } if(argc > 1) name = argv[1]; else name = mboxname; } } user = getenv("user"); if(user == nil) user = "******"; home = getenv("home"); if(home == nil) home = getenv("HOME"); if(home == nil) error("can't find $home"); if(mailboxdir == nil) mailboxdir = estrstrdup(home, "/mail"); if(outgoing == nil) outgoing = estrstrdup(mailboxdir, "/outgoing"); mbox.ctlfd = fsopen(mailfs, estrstrdup(mboxname, "/ctl"), OWRITE); if(mbox.ctlfd == nil) error("can't open %s: %r", estrstrdup(mboxname, "/ctl")); fsname = estrdup(name); if(newdir && argc > 0){ s = emalloc(5+strlen(mailboxdir)+strlen(mboxname)+strlen(name)+10+1); for(i=0; i<10; i++){ sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname); if(fswrite(mbox.ctlfd, s, strlen(s)) >= 0) break; err[0] = '\0'; errstr(err, sizeof err); if(strstr(err, "mbox name in use") == nil) error("can't create directory %s for mail: %s", name, err); free(fsname); fsname = emalloc(strlen(name)+10); sprint(fsname, "%s-%d", name, i); } if(i == 10) error("can't open %s/%s: %r", mailboxdir, mboxname); free(s); } s = estrstrdup(fsname, "/"); mbox.name = estrstrdup(maildir, s); mbox.level= 0; readmbox(&mbox, maildir, s); home = getenv("home"); if(home == nil) home = "/"; wbox = newwindow(); winname(wbox, mbox.name); wintagwrite(wbox, "Put Mail Delmesg ", 3+1+4+1+7+1); threadcreate(mainctl, wbox, STACK); fmtstrinit(&fmt); fmtprint(&fmt, "Mail"); if(shortmenu) fmtprint(&fmt, " -%c", "sS"[shortmenu-1]); if(outgoing) fmtprint(&fmt, " -o %s", outgoing); fmtprint(&fmt, " %s", name); cmd = fmtstrflush(&fmt); if(cmd == nil) sysfatal("out of memory"); winsetdump(wbox, "/acme/mail", cmd); mbox.w = wbox; mesgmenu(wbox, &mbox); winclean(wbox); /* wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */ wctlfd = -1; cplumb = chancreate(sizeof(Plumbmsg*), 0); cplumbshow = chancreate(sizeof(Plumbmsg*), 0); if(strcmp(name, "mbox") == 0){ /* * Avoid creating multiple windows to send mail by only accepting * sendmail plumb messages if we're reading the main mailbox. */ plumbsendmailfd = plumbopenfid("sendmail", OREAD|OCEXEC); cplumbsend = chancreate(sizeof(Plumbmsg*), 0); proccreate(plumbsendproc, nil, STACK); threadcreate(plumbsendthread, nil, STACK); } /* start plumb reader as separate proc ... */ proccreate(plumbproc, nil, STACK); proccreate(plumbshowproc, nil, STACK); threadcreate(plumbshowthread, nil, STACK); fswrite(mbox.ctlfd, "refresh", 7); /* ... and use this thread to read the messages */ plumbthread(); }
void main(int argc, char **argv) { int fd; char *arg, cmdbuf[1024]; Cmd *c; rfork(RFNAMEG); Binit(&in, 0, OREAD); Binit(&out, 1, OWRITE); ARGBEGIN{ case 'a': loggedin = 1; if(readmbox(EARGF(usage())) < 0) exits(nil); break; case 'd': debug++; if((fd = create(EARGF(usage()), OWRITE, 0666)) >= 0 && fd != 2){ dup(fd, 2); close(fd); } break; case 'p': passwordinclear = 1; break; case 'r': strecpy(tmpaddr, tmpaddr+sizeof tmpaddr, EARGF(usage())); if(arg = strchr(tmpaddr, '!')) *arg = '\0'; peeraddr = tmpaddr; break; case 't': tlscert = readcert(EARGF(usage()), &ntlscert); if(tlscert == nil){ senderr("cannot read TLS certificate: %r"); exits(nil); } break; }ARGEND /* do before TLS */ if(peeraddr == nil) peeraddr = remoteaddr(0,0); hello(); while(Bflush(&out), getcrnl(cmdbuf, sizeof cmdbuf) > 0){ arg = nextarg(cmdbuf); for(c=cmdtab; c->name; c++) if(cistrcmp(c->name, cmdbuf) == 0) break; if(c->name == 0){ senderr("unknown command %s", cmdbuf); continue; } if(c->needauth && !loggedin){ senderr("%s requires authentication", cmdbuf); continue; } (*c->f)(arg); } exits(nil); }