📄 marshal.c
字号:
fatal("input error"); if(n == 0) break; m = enc64(obuf, sizeof(obuf), buf, n); if(Bwrite(out, obuf, m) < 0) fatal("output error"); } lastchar = '\n';}// pass message to sendmail, make sure body starts with a newlinevoidcopy(Biobuf *in, Biobuf *out){ char buf[4*1024]; int n; for(;;){ n = Bread(in, buf, sizeof(buf)); if(n < 0) fatal("input error"); if(n == 0) break; if(Bwrite(out, buf, n) < 0) fatal("output error"); }}voidattachment(Attach *a, Biobuf *out){ Biobuf *f; char *p; // if it's already mime encoded, just copy if(strcmp(a->type, "mime") == 0){ f = Bopen(a->path, OREAD); if(f == nil){ /* hack: give marshal time to stdin, before we kill it (for dead.letter) */ sleep(500); postnote(PNPROC, pid, "interrupt"); sysfatal("opening %s: %r", a->path); } copy(f, out); Bterm(f); } // if it's not already mime encoded ... if(strcmp(a->type, "text/plain") != 0) Bprint(out, "Content-Type: %s\n", a->type); if(a->ainline){ Bprint(out, "Content-Disposition: inline\n"); } else { p = strrchr(a->path, '/'); if(p == nil) p = a->path; else p++; Bprint(out, "Content-Disposition: attachment; filename=%Z\n", p); } f = Bopen(a->path, OREAD); if(f == nil){ /* hack: give marshal time to stdin, before we kill it (for dead.letter) */ sleep(500); postnote(PNPROC, pid, "interrupt"); sysfatal("opening %s: %r", a->path); } /* dump our local 'From ' line when passing along mail messages */ if(strcmp(a->type, "message/rfc822") == 0){ p = Brdline(f, '\n'); if(strncmp(p, "From ", 5) != 0) Bseek(f, 0, 0); } if(a->ctype->display){ body(f, out, strcmp(a->type, "text/plain") == 0); } else { Bprint(out, "Content-Transfer-Encoding: base64\n"); body64(f, out); } Bterm(f);}char *ascwday[] ={ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};char *ascmon[] ={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};intprintdate(Biobuf *b){ Tm *tm; int tz; tm = localtime(time(0)); tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60); return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n", ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900+tm->year, tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);}intprintfrom(Biobuf *b){ return Bprint(b, "From: %s\n", user);}intprintto(Biobuf *b, Addr *a){ int i; if(Bprint(b, "To: %s", a->v) < 0) return -1; i = 0; for(a = a->next; a != nil; a = a->next) if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0) return -1; if(Bprint(b, "\n") < 0) return -1; return 0;}intprintcc(Biobuf *b, Addr *a){ int i; if(a == nil) return 0; if(Bprint(b, "CC: %s", a->v) < 0) return -1; i = 0; for(a = a->next; a != nil; a = a->next) if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0) return -1; if(Bprint(b, "\n") < 0) return -1; return 0;}intprintsubject(Biobuf *b, char *subject){ return Bprint(b, "Subject: %U\n", subject);}intprintinreplyto(Biobuf *out, char *dir){ String *s = s_copy(dir); char buf[256]; int fd; int n; s_append(s, "/messageid"); fd = open(s_to_c(s), OREAD); s_free(s); if(fd < 0) return 0; n = read(fd, buf, sizeof(buf)-1); close(fd); if(n <= 0) return 0; buf[n] = 0; return Bprint(out, "In-Reply-To: %s\n", buf);}Attach*mkattach(char *file, char *type, int ainline){ Ctype *c; Attach *a; char ftype[64]; char *p; int n, pfd[2]; if(file == nil) return nil; if(access(file, 4) == -1){ fprint(2, "%s: %s can't read file\n", argv0, file); return nil; } a = emalloc(sizeof(*a)); a->path = file; a->next = nil; a->type = type; a->ainline = ainline; a->ctype = nil; if(type != nil){ for(c = ctype; ; c++) if(strncmp(type, c->type, strlen(c->type)) == 0){ a->ctype = c; break; } return a; } // pick a type depending on extension p = strchr(file, '.'); if(p != nil) p++; // check the builtin extensions if(p != nil){ for(c = ctype; c->ext != nil; c++) if(strcmp(p, c->ext) == 0){ a->type = c->type; a->ctype = c; return a; } } // try the mime types file if(p != nil){ if(mimetypes == nil) readmimetypes(); for(c = mimetypes; c != nil && c->ext != nil; c++) if(strcmp(p, c->ext) == 0){ a->type = c->type; a->ctype = c; return a; } } // run file to figure out the type a->type = "application/octet-stream"; // safest default if(pipe(pfd) < 0) return a; switch(fork()){ case -1: break; case 0: close(pfd[1]); close(0); dup(pfd[0], 0); close(1); dup(pfd[0], 1); execl("/bin/file", "file", "-m", file, nil); exits(0); default: close(pfd[0]); n = read(pfd[1], ftype, sizeof(ftype)); if(n > 0){ ftype[n-1] = 0; a->type = estrdup(ftype); } close(pfd[1]); waitpid(); break; } for(c = ctype; ; c++) if(strncmp(a->type, c->type, strlen(c->type)) == 0){ a->ctype = c; break; } return a;}char*mkboundary(void){ char buf[32]; int i; srand((time(0)<<16)|getpid()); strcpy(buf, "upas-"); for(i = 5; i < sizeof(buf)-1; i++) buf[i] = 'a' + nrand(26); buf[i] = 0; return estrdup(buf);}// copy types to two fd'sstatic voidtee(int in, int out1, int out2){ char buf[8*1024]; int n; for(;;){ n = read(in, buf, sizeof(buf)); if(n <= 0) break; if(write(out1, buf, n) < 0) break; if(write(out2, buf, n) < 0) break; }}// print the unix from lineintprintunixfrom(int fd){ Tm *tm; int tz; tm = localtime(time(0)); tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60); return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n", user, ascwday[tm->wday], ascmon[tm->mon], tm->mday, tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900+tm->year);}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 intopenfolder(char *rcvr){ char *p; int c; String *file; Dir *d; int fd; int scarey; file = s_new(); mboxpath("f", user, file, 0); // if $mail/f exists, store there, otherwise in $mail d = dirstat(s_to_c(file)); if(d == nil || d->qid.type != QTDIR){ scarey = 1; file->ptr -= 1; } else { s_putc(file, '/'); scarey = 0; } 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, "%s: won't overwrite %s\n", argv0, s_to_c(file)); s_free(file); return -1; } fd = open(s_to_c(file), OWRITE); if(fd < 0) fd = create(s_to_c(file), OWRITE, 0660); s_free(file); return fd;}// start up sendmail and return an fd to talk to it withintsendmail(Addr *to, Addr *cc, int *pid, char *rcvr){ char **av, **v; int ac, fd; int pfd[2]; String *cmd; Addr *a; fd = -1; if(rcvr != nil) fd = openfolder(rcvr); ac = 0; for(a = to; a != nil; a = a->next) ac++; for(a = cc; a != nil; a = a->next) ac++; v = av = emalloc(sizeof(char*)*(ac+20)); ac = 0; v[ac++] = "sendmail"; if(xflag) v[ac++] = "-x"; if(rflag) v[ac++] = "-r"; if(lbflag) v[ac++] = "-#"; if(dflag) v[ac++] = "-d"; for(a = to; a != nil; a = a->next) v[ac++] = a->v; for(a = cc; a != nil; a = a->next) v[ac++] = a->v; v[ac] = 0; if(pipe(pfd) < 0) fatal("%r"); switch(*pid = rfork(RFFDG|RFREND|RFPROC|RFENVG)){ case -1: fatal("%r"); break; case 0: if(holding) close(holding); close(pfd[1]); dup(pfd[0], 0); close(pfd[0]); if(rcvr != nil){ if(pipe(pfd) < 0) fatal("%r"); switch(fork()){ case -1: fatal("%r"); break; case 0: close(pfd[0]); seek(fd, 0, 2); printunixfrom(fd); tee(0, pfd[1], fd); write(fd, "\n", 1); exits(0); default: close(fd); close(pfd[1]); dup(pfd[0], 0); break; } } if(replymsg != nil) putenv("replymsg", replymsg); cmd = mboxpath("pipefrom", login, s_new(), 0); exec(s_to_c(cmd), av); exec("/bin/myupassend", av); exec("/bin/upas/send", av); fatal("execing: %r"); break; default: if(rcvr != nil) close(fd); close(pfd[0]); break; } return pfd[1];}// start up pgp process and return an fd to talk to it with.// its standard output will be the original fd, which goes to sendmail.intpgpfilter(int *pid, int fd, int pgpflag){ char **av, **v; int ac; int pfd[2]; v = av = emalloc(sizeof(char*)*8); ac = 0; v[ac++] = "pgp"; v[ac++] = "-fat"; /* operate as a filter, generate text */ if(pgpflag & PGPsign) v[ac++] = "-s"; if(pgpflag & PGPencrypt) v[ac++] = "-e"; v[ac] = 0; if(pipe(pfd) < 0) fatal("%r"); switch(*pid = fork()){ case -1: fatal("%r"); break; case 0: close(pfd[1]); dup(pfd[0], 0); close(pfd[0]); dup(fd, 1); close(fd); /* add newline to avoid confusing pgp output with 822 headers */ write(1, "\n", 1); exec("/bin/pgp", av); fatal("execing: %r"); break; default: close(pfd[0]); break; } close(fd); return pfd[1];}// wait for sendmail and pgp to exit; exit here if either failedchar*waitforsubprocs(void){ Waitmsg *w; char *err; err = nil; while((w = wait()) != nil){ if(w->pid == pid || w->pid == pgppid){ if(w->msg[0] != 0) err = estrdup(w->msg); } free(w); } if(err) exits(err); return nil;}intcistrncmp(char *a, char *b, int n){ while(n-- > 0){ if(tolower(*a++) != tolower(*b++)) return -1; } return 0;}intcistrcmp(char *a, char *b){ for(;;){ if(tolower(*a) != tolower(*b++)) return -1; if(*a++ == 0) break; } return 0;}static uchar t64d[256];static char t64e[64];static voidinit64(void){ int c, i; memset(t64d, 255, 256); memset(t64e, '=', 64); i = 0; for(c = 'A'; c <= 'Z'; c++){ t64e[i] = c; t64d[c] = i++; } for(c = 'a'; c <= 'z'; c++){ t64e[i] = c; t64d[c] = i++; } for(c = '0'; c <= '9'; c++){ t64e[i] = c; t64d[c] = i++; } t64e[i] = '+'; t64d['+'] = i++; t64e[i] = '/'; t64d['/'] = i;}intenc64(char *out, int lim, uchar *in, int n){ int i; ulong b24; char *start = out; char *e = out + lim; if(t64e[0] == 0) init64(); for(i = 0; i < n/3; i++){ b24 = (*in++)<<16; b24 |= (*in++)<<8; b24 |= *in++; if(out + 5 >= e) goto exhausted; *out++ = t64e[(b24>>18)]; *out++ = t64e[(b24>>12)&0x3f]; *out++ = t64e[(b24>>6)&0x3f]; *out++ = t64e[(b24)&0x3f]; if((i%18) == 17) *out++ = '\n'; } switch(n%3){ case 2: b24 = (*in++)<<16; b24 |= (*in)<<8; if(out + 4 >= e) goto exhausted; *out++ = t64e[(b24>>18)]; *out++ = t64e[(b24>>12)&0x3f]; *out++ = t64e[(b24>>6)&0x3f]; break; case 1: b24 = (*in)<<16;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -