📄 nedmail.c
字号:
helpcmd(Cmd*, Message *m){ int i; Bprint(&out, "Commands are of the form [<range>] <command> [args]\n"); Bprint(&out, "<range> := <addr> | <addr>','<addr>| 'g'<search>\n"); Bprint(&out, "<addr> := '.' | '$' | '^' | <number> | <search> | <addr>'+'<addr> | <addr>'-'<addr>\n"); Bprint(&out, "<search> := '/'<regexp>'/' | '?'<regexp>'?' | '%%'<regexp>'%%'\n"); Bprint(&out, "<command> :=\n"); for(i = 0; cmdtab[i].cmd != nil; i++) Bprint(&out, "%s\n", cmdtab[i].help); return m;}inttomailer(char **av){ Waitmsg *w; int pid, i; // start the mailer and get out of the way switch(pid = fork()){ case -1: fprint(2, "can't fork: %r\n"); return -1; case 0: Bprint(&out, "!/bin/upas/marshal"); for(i = 1; av[i]; i++){ if(strchr(av[i], ' ') != nil) Bprint(&out, " '%s'", av[i]); else Bprint(&out, " %s", av[i]); } Bprint(&out, "\n"); Bflush(&out); av[0] = "marshal"; chdir(wd); exec("/bin/upas/marshal", av); fprint(2, "couldn't exec /bin/upas/marshal\n"); exits(0); default: w = wait(); if(w == nil){ if(interrupted) postnote(PNPROC, pid, "die"); waitpid(); return -1; } if(w->msg[0]){ fprint(2, "mailer failed: %s\n", w->msg); free(w); return -1; } free(w); Bprint(&out, "!\n"); break; } return 0;}//// like tokenize but obey "" quoting//inttokenize822(char *str, char **args, int max){ int na; int intok = 0, inquote = 0; if(max <= 0) return 0; for(na=0; ;str++) switch(*str) { case ' ': case '\t': if(inquote) goto Default; /* fall through */ case '\n': *str = 0; if(!intok) continue; intok = 0; if(na < max) continue; /* fall through */ case 0: return na; case '"': inquote ^= 1; /* fall through */ Default: default: if(intok) continue; args[na++] = str; intok = 1; }}Message*rcmd(Cmd *c, Message *m){ char *av[128]; int i, ai = 1; Message *nm; char *addr; String *path = nil; String *rpath; String *subject = nil; String *from; if(m == &top){ Bprint(&out, "!address\n"); return nil; } addr = nil; for(nm = m; nm != ⊤ nm = nm->parent){ if(*nm->replyto != 0){ addr = nm->replyto; break; } } if(addr == nil){ Bprint(&out, "!no reply address\n"); return nil; } if(nm == &top){ print("!noone to reply to\n"); return nil; } for(nm = m; nm != ⊤ nm = nm->parent){ if(*nm->subject){ av[ai++] = "-s"; subject = addrecolon(nm->subject); av[ai++] = s_to_c(subject);; break; } } av[ai++] = "-R"; rpath = rooted(s_clone(m->path)); av[ai++] = s_to_c(rpath); if(strchr(c->av[0], 'f') != nil){ fcmd(c, m); av[ai++] = "-F"; } if(strchr(c->av[0], 'R') != nil){ av[ai++] = "-t"; av[ai++] = "message/rfc822"; av[ai++] = "-A"; path = rooted(extendpath(m->path, "raw")); av[ai++] = s_to_c(path); } for(i = 1; i < c->an && ai < nelem(av)-1; i++) av[ai++] = c->av[i]; from = s_copy(addr); ai += tokenize822(s_to_c(from), &av[ai], nelem(av) - ai); av[ai] = 0; if(tomailer(av) < 0) m = nil; s_free(path); s_free(rpath); s_free(subject); s_free(from); return m;}Message*mcmd(Cmd *c, Message *m){ char **av; int i, ai; String *path; if(m == &top){ Bprint(&out, "!address\n"); return nil; } if(c->an < 2){ fprint(2, "!usage: M list-of addresses\n"); return nil; } ai = 1; av = malloc(sizeof(char*)*(c->an + 8)); av[ai++] = "-t"; if(m->parent == &top) av[ai++] = "message/rfc822"; else av[ai++] = "mime"; av[ai++] = "-A"; path = rooted(extendpath(m->path, "raw")); av[ai++] = s_to_c(path); if(strchr(c->av[0], 'M') == nil) av[ai++] = "-n"; for(i = 1; i < c->an; i++) av[ai++] = c->av[i]; av[ai] = 0; if(tomailer(av) < 0) m = nil; if(path != nil) s_free(path); free(av); return m;}Message*acmd(Cmd *c, Message *m){ char *av[128]; int i, ai; String *from, *to, *cc, *path = nil, *subject = nil; if(m == &top){ Bprint(&out, "!address\n"); return nil; } ai = 1; if(*m->subject){ av[ai++] = "-s"; subject = addrecolon(m->subject); av[ai++] = s_to_c(subject); } if(strchr(c->av[0], 'A') != nil){ av[ai++] = "-t"; av[ai++] = "message/rfc822"; av[ai++] = "-A"; path = rooted(extendpath(m->path, "raw")); av[ai++] = s_to_c(path); } for(i = 1; i < c->an && ai < nelem(av)-1; i++) av[ai++] = c->av[i]; from = s_copy(m->from); ai += tokenize822(s_to_c(from), &av[ai], nelem(av) - ai); to = s_copy(m->to); ai += tokenize822(s_to_c(to), &av[ai], nelem(av) - ai); cc = s_copy(m->cc); ai += tokenize822(s_to_c(cc), &av[ai], nelem(av) - ai); av[ai] = 0; if(tomailer(av) < 0) return nil; s_free(from); s_free(to); s_free(cc); s_free(subject); s_free(path); return m;}String *relpath(char *path, String *to){ if (*path=='/' || strncmp(path, "./", 2) == 0 || strncmp(path, "../", 3) == 0) { to = s_append(to, path); } else if(mbpath) { to = s_append(to, s_to_c(mbpath)); to->ptr = strrchr(to->base, '/')+1; s_append(to, path); } return to;}intappendtofile(Message *m, char *part, char *base, int mbox){ String *file, *h; int in, out, rv; file = extendpath(m->path, part); in = open(s_to_c(file), OREAD); if(in < 0){ fprint(2, "!message disappeared\n"); return -1; } s_reset(file); relpath(base, file); if(sysisdir(s_to_c(file))){ s_append(file, "/"); if(m->filename && strchr(m->filename, '/') == nil) s_append(file, m->filename); else { s_append(file, "att.XXXXXXXXXXX"); mktemp(s_to_c(file)); } } if(mbox) out = open(s_to_c(file), OWRITE); else out = open(s_to_c(file), OWRITE|OTRUNC); if(out < 0){ out = create(s_to_c(file), OWRITE, 0666); if(out < 0){ fprint(2, "!can't open %s: %r\n", s_to_c(file)); close(in); s_free(file); return -1; } } if(mbox) seek(out, 0, 2); // put on a 'From ' line if(mbox){ while(m->parent != &top) m = m->parent; h = file2string(m->path, "unixheader"); fprint(out, "%s", s_to_c(h)); s_free(h); } // copy the message escaping what we have to ad adding newlines if we have to if(mbox) rv = appendfiletombox(in, out); else rv = appendfiletofile(in, out); close(in); close(out); if(rv >= 0) print("!saved in %s\n", s_to_c(file)); s_free(file); return rv;}Message*scmd(Cmd *c, Message *m){ char *file; if(m == &top){ Bprint(&out, "!address\n"); return nil; } switch(c->an){ case 1: file = "stored"; break; case 2: file = c->av[1]; break; default: fprint(2, "!usage: s filename\n"); return nil; } if(appendtofile(m, "raw", file, 1) < 0) return nil; m->stored = 1; return m;}Message*wcmd(Cmd *c, Message *m){ char *file; if(m == &top){ Bprint(&out, "!address\n"); return nil; } switch(c->an){ case 2: file = c->av[1]; break; case 1: if(*m->filename == 0){ fprint(2, "!usage: w filename\n"); return nil; } file = strrchr(m->filename, '/'); if(file != nil) file++; else file = m->filename; break; default: fprint(2, "!usage: w filename\n"); return nil; } if(appendtofile(m, "body", file, 0) < 0) return nil; m->stored = 1; return m;}char *specialfile[] ={ "pipeto", "pipefrom", "L.mbox", "forward", "names"};// return 1 if this is a special filestatic intspecial(String *s){ char *p; int i; p = strrchr(s_to_c(s), '/'); if(p == nil) p = s_to_c(s); else p++; for(i = 0; i < nelem(specialfile); i++) if(strcmp(p, specialfile[i]) == 0) return 1; return 0;}// open the folder using the recipients account namestatic String*foldername(char *rcvr){ char *p; int c; String *file; Dir *d; int scarey; file = s_new(); mboxpath("f", user, file, 0); d = dirstat(s_to_c(file)); // if $mail/f exists, store there, otherwise in $mail s_restart(file); if(d && d->qid.type == QTDIR){ scarey = 0; s_append(file, "f/"); } else { scarey = 1; } free(d); p = strrchr(rcvr, '!'); if(p != nil) rcvr = p+1; while(*rcvr && *rcvr != '@'){ c = *rcvr++; if(c == '/') c = '_'; s_putc(file, c); } s_terminate(file); if(scarey && special(file)){ fprint(2, "!won't overwrite %s\n", s_to_c(file)); s_free(file); return nil; } return file;}Message*fcmd(Cmd *c, Message *m){ String *folder; if(c->an > 1){ fprint(2, "!usage: f takes no arguments\n"); return nil; } if(m == &top){ Bprint(&out, "!address\n"); return nil; } folder = foldername(m->from); if(folder == nil) return nil; if(appendtofile(m, "raw", s_to_c(folder), 1) < 0){ s_free(folder); return nil; } s_free(folder); m->stored = 1; return m;}voidsystem(char *cmd, char **av, int in){ int pid; switch(pid=fork()){ case -1: return; case 0: if(in >= 0){ close(0); dup(in, 0); close(in); } if(wd[0] != 0) chdir(wd); exec(cmd, av); fprint(2, "!couldn't exec %s\n", cmd); exits(0); default: if(in >= 0) close(in); while(waitpid() < 0){ if(!interrupted) break; postnote(PNPROC, pid, "die"); continue; } break; }}Message*bangcmd(Cmd *c, Message *m){ char cmd[4*1024]; char *p, *e; char *av[4]; int i; cmd[0] = 0; p = cmd; e = cmd+sizeof(cmd); for(i = 1; i < c->an; i++) p = seprint(p, e, "%s ", c->av[i]); av[0] = "rc"; av[1] = "-c"; av[2] = cmd; av[3] = 0; system("/bin/rc", av, -1); Bprint(&out, "!\n"); return m;}Message*xpipecmd(Cmd *c, Message *m, char *part){ char cmd[128]; char *p, *e; char *av[4]; String *path; int i, fd; if(c->an < 2){ Bprint(&out, "!usage: | cmd\n"); return nil; } if(m == &top){ Bprint(&out, "!address\n"); return nil; } path = extendpath(m->path, part); fd = open(s_to_c(path), OREAD); s_free(path); if(fd < 0){ // compatibility with older upas/fs path = extendpath(m->path, "raw"); fd = open(s_to_c(path), OREAD); s_free(path); } if(fd < 0){ fprint(2, "!message disappeared\n"); return nil; } p = cmd; e = cmd+sizeof(cmd); cmd[0] = 0; for(i = 1; i < c->an; i++) p = seprint(p, e, "%s ", c->av[i]); av[0] = "rc"; av[1] = "-c"; av[2] = cmd; av[3] = 0; system("/bin/rc", av, fd); /* system closes fd */ Bprint(&out, "!\n"); return m;}Message*pipecmd(Cmd *c, Message *m){ return xpipecmd(c, m, "body");}Message*rpipecmd(Cmd *c, Message *m){ return xpipecmd(c, m, "rawunix");}voidclosemb(void){ int fd; fd = open("/mail/fs/ctl", ORDWR); if(fd < 0) sysfatal("can't open /mail/fs/ctl: %r"); // close current mailbox if(*mbname && strcmp(mbname, "mbox") != 0) fprint(fd, "close %s", mbname); close(fd);}intswitchmb(char *file, char *singleton){ char *p; int n, fd; String *path; char buf[256]; // if the user didn't say anything and there // is an mbox mounted already, use that one // so that the upas/fs -fdefault default is honored. if(file || (singleton && access(singleton, 0)<0) || (!singleton && access("/mail/fs/mbox", 0)<0)){ if(file == nil) file = "mbox"; // close current mailbox closemb(); didopen = 1; fd = open("/mail/fs/ctl", ORDWR); if(fd < 0) sysfatal("can't open /mail/fs/ctl: %r"); path = s_new(); // get an absolute path to the mail box if(strncmp(file, "./", 2) == 0){ // resolve path here since upas/fs doesn't know // our working directory if(getwd(buf, sizeof(buf)-strlen(file)) == nil){ fprint(2, "!can't get working directory: %s\n", buf); return -1; } s_append(path, buf); s_append(path, file+1); } else { mboxpath(file, user, path, 0); } // make up a handle to use when talking to fs p = strrchr(file, '/'); if(p == nil){ // if its in the mailbox directory, just use the name strncpy(mbname, file, sizeof(mbname)); mbname[sizeof(mbname)-1] = 0; } else { // make up a mailbox name p = strrchr(s_to_c(path), '/'); p++; if(*p == 0){ fprint(2, "!bad mbox name"); return -1; } strncpy(mbname, p, sizeof(mbname)); mbname[sizeof(mbname)-1] = 0; n = strlen(mbname); if(n > Elemlen-12) n = Elemlen-12; sprint(mbname+n, "%ld", time(0)); } if(fprint(fd, "open %s %s", s_to_c(path), mbname) < 0){ fprint(2, "!can't 'open %s %s': %r\n", file, mbname); s_free(path); return -1; } close(fd); }else if (singleton && access(singleton, 0)==0 && strncmp(singleton, "/mail/fs/", 9) == 0){ if ((p = strchr(singleton +10, '/')) == nil){ fprint(2, "!bad mbox name"); return -1; } n = p-(singleton+9); strncpy(mbname, singleton+9, n); mbname[n+1] = 0; path = s_reset(nil); mboxpath(mbname, user, path, 0); }else{ path = s_reset(nil); mboxpath("mbox", user, path, 0); strcpy(mbname, "mbox"); } sprint(root, "/mail/fs/%s", mbname); if(getwd(wd, sizeof(wd)) == 0) wd[0] = 0; if(singleton == nil && chdir(root) >= 0) strcpy(root, "."); rootlen = strlen(root); if(mbpath != nil) s_free(mbpath); mbpath = path; return 0;}// like tokenize but for into linesintlineize(char *s, char **f, int n){ int i; for(i = 0; *s && i < n; i++){ f[i] = s; s = strchr(s, '\n'); if(s == nil) break; *s++ = 0; } return i;}String*rooted(String *s){ static char buf[256]; if(strcmp(root, ".") != 0) return s; snprint(buf, sizeof(buf), "/mail/fs/%s/%s", mbname, s_to_c(s)); s_free(s); return s_copy(buf);}intplumb(Message *m, Ctype *cp){ String *s; Plumbmsg *pm; static int fd = -2; if(cp->plumbdest == nil) return -1; if(fd < -1) fd = plumbopen("send", OWRITE); if(fd < 0) return -1; pm = mallocz(sizeof(Plumbmsg), 1); pm->src = strdup("mail"); if(*cp->plumbdest) pm->dst = strdup(cp->plumbdest); pm->wdir = nil; pm->type = strdup("text"); pm->ndata = -1; s = rooted(extendpath(m->path, "body")); if(cp->ext != nil){ s_append(s, "."); s_append(s, cp->ext); } pm->data = strdup(s_to_c(s)); s_free(s); plumbsend(fd, pm); plumbfree(pm); return 0;}voidregerror(char*){}String*addrecolon(char *s){ String *str; if(cistrncmp(s, "re:", 3) != 0){ str = s_copy("Re: "); s_append(str, s); } else str = s_copy(s); return str;}voidexitfs(char *rv){ if(startedfs) unmount(nil, "/mail/fs");chdir("/sys/src/cmd/upas/ned"); exits(rv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -