Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 7ce2007c 2006-02-12 devnull #include <thread.h>
3 7ce2007c 2006-02-12 devnull #include <9pclient.h>
4 5cdb1798 2005-10-29 devnull #include <ctype.h>
5 5cdb1798 2005-10-29 devnull
6 7ce2007c 2006-02-12 devnull enum
7 7ce2007c 2006-02-12 devnull {
8 7ce2007c 2006-02-12 devnull STACK = 32768
9 7ce2007c 2006-02-12 devnull };
10 7ce2007c 2006-02-12 devnull
11 b5f65921 2006-02-11 devnull #define inline _inline
12 b5f65921 2006-02-11 devnull
13 5cdb1798 2005-10-29 devnull typedef struct Attach Attach;
14 5cdb1798 2005-10-29 devnull typedef struct Alias Alias;
15 5cdb1798 2005-10-29 devnull typedef struct Addr Addr;
16 5cdb1798 2005-10-29 devnull typedef struct Ctype Ctype;
17 5cdb1798 2005-10-29 devnull
18 5cdb1798 2005-10-29 devnull struct Attach {
19 5cdb1798 2005-10-29 devnull Attach *next;
20 5cdb1798 2005-10-29 devnull char *path;
21 7ce2007c 2006-02-12 devnull int fd;
22 5cdb1798 2005-10-29 devnull char *type;
23 b5f65921 2006-02-11 devnull int inline;
24 5cdb1798 2005-10-29 devnull Ctype *ctype;
25 5cdb1798 2005-10-29 devnull };
26 5cdb1798 2005-10-29 devnull
27 5cdb1798 2005-10-29 devnull struct Alias
28 5cdb1798 2005-10-29 devnull {
29 5cdb1798 2005-10-29 devnull Alias *next;
30 5cdb1798 2005-10-29 devnull int n;
31 5cdb1798 2005-10-29 devnull Addr *addr;
32 5cdb1798 2005-10-29 devnull };
33 5cdb1798 2005-10-29 devnull
34 5cdb1798 2005-10-29 devnull struct Addr
35 5cdb1798 2005-10-29 devnull {
36 5cdb1798 2005-10-29 devnull Addr *next;
37 5cdb1798 2005-10-29 devnull char *v;
38 5cdb1798 2005-10-29 devnull };
39 5cdb1798 2005-10-29 devnull
40 5cdb1798 2005-10-29 devnull enum {
41 5cdb1798 2005-10-29 devnull Hfrom,
42 5cdb1798 2005-10-29 devnull Hto,
43 5cdb1798 2005-10-29 devnull Hcc,
44 5cdb1798 2005-10-29 devnull Hbcc,
45 5cdb1798 2005-10-29 devnull Hsender,
46 5cdb1798 2005-10-29 devnull Hreplyto,
47 5cdb1798 2005-10-29 devnull Hinreplyto,
48 5cdb1798 2005-10-29 devnull Hdate,
49 5cdb1798 2005-10-29 devnull Hsubject,
50 5cdb1798 2005-10-29 devnull Hmime,
51 5cdb1798 2005-10-29 devnull Hpriority,
52 5cdb1798 2005-10-29 devnull Hmsgid,
53 5cdb1798 2005-10-29 devnull Hcontent,
54 5cdb1798 2005-10-29 devnull Hx,
55 5cdb1798 2005-10-29 devnull Hprecedence,
56 cbeb0b26 2006-04-01 devnull Nhdr
57 5cdb1798 2005-10-29 devnull };
58 5cdb1798 2005-10-29 devnull
59 5cdb1798 2005-10-29 devnull enum {
60 5cdb1798 2005-10-29 devnull PGPsign = 1,
61 cbeb0b26 2006-04-01 devnull PGPencrypt = 2
62 5cdb1798 2005-10-29 devnull };
63 5cdb1798 2005-10-29 devnull
64 5cdb1798 2005-10-29 devnull char *hdrs[Nhdr] = {
65 5cdb1798 2005-10-29 devnull [Hfrom] "from:",
66 5cdb1798 2005-10-29 devnull [Hto] "to:",
67 5cdb1798 2005-10-29 devnull [Hcc] "cc:",
68 5cdb1798 2005-10-29 devnull [Hbcc] "bcc:",
69 5cdb1798 2005-10-29 devnull [Hreplyto] "reply-to:",
70 5cdb1798 2005-10-29 devnull [Hinreplyto] "in-reply-to:",
71 5cdb1798 2005-10-29 devnull [Hsender] "sender:",
72 5cdb1798 2005-10-29 devnull [Hdate] "date:",
73 5cdb1798 2005-10-29 devnull [Hsubject] "subject:",
74 5cdb1798 2005-10-29 devnull [Hpriority] "priority:",
75 5cdb1798 2005-10-29 devnull [Hmsgid] "message-id:",
76 5cdb1798 2005-10-29 devnull [Hmime] "mime-",
77 5cdb1798 2005-10-29 devnull [Hcontent] "content-",
78 5cdb1798 2005-10-29 devnull [Hx] "x-",
79 cbeb0b26 2006-04-01 devnull [Hprecedence] "precedence"
80 5cdb1798 2005-10-29 devnull };
81 5cdb1798 2005-10-29 devnull
82 5cdb1798 2005-10-29 devnull struct Ctype {
83 5cdb1798 2005-10-29 devnull char *type;
84 5cdb1798 2005-10-29 devnull char *ext;
85 5cdb1798 2005-10-29 devnull int display;
86 5cdb1798 2005-10-29 devnull };
87 5cdb1798 2005-10-29 devnull
88 5cdb1798 2005-10-29 devnull Ctype ctype[] = {
89 5cdb1798 2005-10-29 devnull { "text/plain", "txt", 1, },
90 5cdb1798 2005-10-29 devnull { "text/html", "html", 1, },
91 5cdb1798 2005-10-29 devnull { "text/html", "htm", 1, },
92 5cdb1798 2005-10-29 devnull { "text/tab-separated-values", "tsv", 1, },
93 5cdb1798 2005-10-29 devnull { "text/richtext", "rtx", 1, },
94 5cdb1798 2005-10-29 devnull { "message/rfc822", "txt", 1, },
95 cbeb0b26 2006-04-01 devnull { "", 0, 0, }
96 5cdb1798 2005-10-29 devnull };
97 5cdb1798 2005-10-29 devnull
98 5cdb1798 2005-10-29 devnull Ctype *mimetypes;
99 5cdb1798 2005-10-29 devnull
100 5cdb1798 2005-10-29 devnull int pid = -1;
101 5cdb1798 2005-10-29 devnull int pgppid = -1;
102 5cdb1798 2005-10-29 devnull
103 5cdb1798 2005-10-29 devnull Attach* mkattach(char*, char*, int);
104 5cdb1798 2005-10-29 devnull int readheaders(Biobuf*, int*, String**, Addr**, int);
105 5cdb1798 2005-10-29 devnull void body(Biobuf*, Biobuf*, int);
106 5cdb1798 2005-10-29 devnull char* mkboundary(void);
107 5cdb1798 2005-10-29 devnull int printdate(Biobuf*);
108 5cdb1798 2005-10-29 devnull int printfrom(Biobuf*);
109 5cdb1798 2005-10-29 devnull int printto(Biobuf*, Addr*);
110 5cdb1798 2005-10-29 devnull int printcc(Biobuf*, Addr*);
111 5cdb1798 2005-10-29 devnull int printsubject(Biobuf*, char*);
112 5cdb1798 2005-10-29 devnull int printinreplyto(Biobuf*, char*);
113 5cdb1798 2005-10-29 devnull int sendmail(Addr*, Addr*, int*, char*);
114 5cdb1798 2005-10-29 devnull void attachment(Attach*, Biobuf*);
115 5cdb1798 2005-10-29 devnull int cistrncmp(char*, char*, int);
116 5cdb1798 2005-10-29 devnull int cistrcmp(char*, char*);
117 5cdb1798 2005-10-29 devnull char* waitforsubprocs(void);
118 5cdb1798 2005-10-29 devnull int enc64(char*, int, uchar*, int);
119 5cdb1798 2005-10-29 devnull Addr* expand(int, char**);
120 5cdb1798 2005-10-29 devnull Alias* readaliases(void);
121 5cdb1798 2005-10-29 devnull Addr* expandline(String**, Addr*);
122 5cdb1798 2005-10-29 devnull void Bdrain(Biobuf*);
123 5cdb1798 2005-10-29 devnull void freeaddr(Addr *);
124 5cdb1798 2005-10-29 devnull int pgpopts(char*);
125 5cdb1798 2005-10-29 devnull int pgpfilter(int*, int, int);
126 5cdb1798 2005-10-29 devnull void readmimetypes(void);
127 5cdb1798 2005-10-29 devnull char* estrdup(char*);
128 5cdb1798 2005-10-29 devnull void* emalloc(int);
129 5cdb1798 2005-10-29 devnull void* erealloc(void*, int);
130 5cdb1798 2005-10-29 devnull void freeaddr(Addr*);
131 5cdb1798 2005-10-29 devnull void freeaddrs(Addr*);
132 5cdb1798 2005-10-29 devnull void freealias(Alias*);
133 5cdb1798 2005-10-29 devnull void freealiases(Alias*);
134 5cdb1798 2005-10-29 devnull int doublequote(Fmt*);
135 7ce2007c 2006-02-12 devnull int mountmail(void);
136 7ce2007c 2006-02-12 devnull int nprocexec;
137 3d038c32 2006-03-31 devnull int rfc2047fmt(Fmt*);
138 3d038c32 2006-03-31 devnull char* mksubject(char*);
139 5cdb1798 2005-10-29 devnull
140 5cdb1798 2005-10-29 devnull int rflag, lbflag, xflag, holding, nflag, Fflag, eightflag, dflag;
141 5cdb1798 2005-10-29 devnull int pgpflag = 0;
142 5cdb1798 2005-10-29 devnull char *user;
143 5cdb1798 2005-10-29 devnull char *login;
144 5cdb1798 2005-10-29 devnull Alias *aliases;
145 5cdb1798 2005-10-29 devnull int rfc822syntaxerror;
146 5cdb1798 2005-10-29 devnull char lastchar;
147 5cdb1798 2005-10-29 devnull char *replymsg;
148 5cdb1798 2005-10-29 devnull
149 7ce2007c 2006-02-12 devnull CFsys *mailfs;
150 7ce2007c 2006-02-12 devnull
151 5cdb1798 2005-10-29 devnull enum
152 5cdb1798 2005-10-29 devnull {
153 5cdb1798 2005-10-29 devnull Ok = 0,
154 5cdb1798 2005-10-29 devnull Nomessage = 1,
155 5cdb1798 2005-10-29 devnull Nobody = 2,
156 cbeb0b26 2006-04-01 devnull Error = -1
157 5cdb1798 2005-10-29 devnull };
158 5cdb1798 2005-10-29 devnull
159 5cdb1798 2005-10-29 devnull #pragma varargck type "Z" char*
160 5cdb1798 2005-10-29 devnull
161 5cdb1798 2005-10-29 devnull void
162 5cdb1798 2005-10-29 devnull usage(void)
163 5cdb1798 2005-10-29 devnull {
164 5cdb1798 2005-10-29 devnull fprint(2, "usage: %s [-Fr#xn] [-s subject] [-c ccrecipient] [-t type] [-aA attachment] [-p[es]] [-R replymsg] -8 | recipient-list\n",
165 5cdb1798 2005-10-29 devnull argv0);
166 7ce2007c 2006-02-12 devnull threadexitsall("usage");
167 5cdb1798 2005-10-29 devnull }
168 5cdb1798 2005-10-29 devnull
169 5cdb1798 2005-10-29 devnull void
170 5cdb1798 2005-10-29 devnull fatal(char *fmt, ...)
171 5cdb1798 2005-10-29 devnull {
172 5cdb1798 2005-10-29 devnull char buf[1024];
173 5cdb1798 2005-10-29 devnull va_list arg;
174 5cdb1798 2005-10-29 devnull
175 5cdb1798 2005-10-29 devnull if(pid >= 0)
176 5cdb1798 2005-10-29 devnull postnote(PNPROC, pid, "die");
177 5cdb1798 2005-10-29 devnull if(pgppid >= 0)
178 5cdb1798 2005-10-29 devnull postnote(PNPROC, pgppid, "die");
179 5cdb1798 2005-10-29 devnull
180 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
181 5cdb1798 2005-10-29 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
182 5cdb1798 2005-10-29 devnull va_end(arg);
183 5cdb1798 2005-10-29 devnull fprint(2, "%s: %s\n", argv0, buf);
184 5cdb1798 2005-10-29 devnull holdoff(holding);
185 7ce2007c 2006-02-12 devnull threadexitsall(buf);
186 5cdb1798 2005-10-29 devnull }
187 5cdb1798 2005-10-29 devnull
188 5cdb1798 2005-10-29 devnull void
189 7ce2007c 2006-02-12 devnull threadmain(int argc, char **argv)
190 5cdb1798 2005-10-29 devnull {
191 5cdb1798 2005-10-29 devnull Attach *first, **l, *a;
192 5cdb1798 2005-10-29 devnull char *subject, *type, *boundary;
193 5cdb1798 2005-10-29 devnull int flags, fd;
194 5cdb1798 2005-10-29 devnull Biobuf in, out, *b;
195 5cdb1798 2005-10-29 devnull Addr *to;
196 5cdb1798 2005-10-29 devnull Addr *cc;
197 5cdb1798 2005-10-29 devnull String *file, *hdrstring;
198 5cdb1798 2005-10-29 devnull int noinput, headersrv;
199 5cdb1798 2005-10-29 devnull int ccargc;
200 5cdb1798 2005-10-29 devnull char *ccargv[32];
201 5cdb1798 2005-10-29 devnull
202 5cdb1798 2005-10-29 devnull noinput = 0;
203 5cdb1798 2005-10-29 devnull subject = nil;
204 5cdb1798 2005-10-29 devnull first = nil;
205 5cdb1798 2005-10-29 devnull l = &first;
206 5cdb1798 2005-10-29 devnull type = nil;
207 5cdb1798 2005-10-29 devnull hdrstring = nil;
208 5cdb1798 2005-10-29 devnull ccargc = 0;
209 5cdb1798 2005-10-29 devnull
210 5cdb1798 2005-10-29 devnull quotefmtinstall();
211 5cdb1798 2005-10-29 devnull fmtinstall('Z', doublequote);
212 3d038c32 2006-03-31 devnull fmtinstall('U', rfc2047fmt);
213 7ce2007c 2006-02-12 devnull threadwaitchan();
214 5cdb1798 2005-10-29 devnull
215 5cdb1798 2005-10-29 devnull ARGBEGIN{
216 5cdb1798 2005-10-29 devnull case 't':
217 7ce2007c 2006-02-12 devnull type = EARGF(usage());
218 5cdb1798 2005-10-29 devnull break;
219 5cdb1798 2005-10-29 devnull case 'a':
220 5cdb1798 2005-10-29 devnull flags = 0;
221 5cdb1798 2005-10-29 devnull goto aflag;
222 5cdb1798 2005-10-29 devnull case 'A':
223 5cdb1798 2005-10-29 devnull flags = 1;
224 5cdb1798 2005-10-29 devnull aflag:
225 7ce2007c 2006-02-12 devnull a = mkattach(EARGF(usage()), type, flags);
226 5cdb1798 2005-10-29 devnull if(a == nil)
227 7ce2007c 2006-02-12 devnull threadexitsall("bad args");
228 5cdb1798 2005-10-29 devnull type = nil;
229 5cdb1798 2005-10-29 devnull *l = a;
230 5cdb1798 2005-10-29 devnull l = &a->next;
231 5cdb1798 2005-10-29 devnull break;
232 5cdb1798 2005-10-29 devnull case 'C':
233 5cdb1798 2005-10-29 devnull if(ccargc >= nelem(ccargv)-1)
234 5cdb1798 2005-10-29 devnull sysfatal("too many cc's");
235 5cdb1798 2005-10-29 devnull ccargv[ccargc] = ARGF();
236 5cdb1798 2005-10-29 devnull if(ccargv[ccargc] == nil)
237 5cdb1798 2005-10-29 devnull usage();
238 5cdb1798 2005-10-29 devnull ccargc++;
239 5cdb1798 2005-10-29 devnull break;
240 5cdb1798 2005-10-29 devnull case 'R':
241 7ce2007c 2006-02-12 devnull replymsg = EARGF(usage());
242 5cdb1798 2005-10-29 devnull break;
243 5cdb1798 2005-10-29 devnull case 's':
244 7ce2007c 2006-02-12 devnull subject = EARGF(usage());
245 5cdb1798 2005-10-29 devnull break;
246 5cdb1798 2005-10-29 devnull case 'F':
247 cbeb0b26 2006-04-01 devnull Fflag = 1; /* file message */
248 5cdb1798 2005-10-29 devnull break;
249 5cdb1798 2005-10-29 devnull case 'r':
250 cbeb0b26 2006-04-01 devnull rflag = 1; /* for sendmail */
251 5cdb1798 2005-10-29 devnull break;
252 5cdb1798 2005-10-29 devnull case 'd':
253 cbeb0b26 2006-04-01 devnull dflag = 1; /* for sendmail */
254 5cdb1798 2005-10-29 devnull break;
255 5cdb1798 2005-10-29 devnull case '#':
256 cbeb0b26 2006-04-01 devnull lbflag = 1; /* for sendmail */
257 5cdb1798 2005-10-29 devnull break;
258 5cdb1798 2005-10-29 devnull case 'x':
259 cbeb0b26 2006-04-01 devnull xflag = 1; /* for sendmail */
260 5cdb1798 2005-10-29 devnull break;
261 cbeb0b26 2006-04-01 devnull case 'n': /* no standard input */
262 5cdb1798 2005-10-29 devnull nflag = 1;
263 5cdb1798 2005-10-29 devnull break;
264 cbeb0b26 2006-04-01 devnull case '8': /* read recipients from rfc822 header */
265 5cdb1798 2005-10-29 devnull eightflag = 1;
266 5cdb1798 2005-10-29 devnull break;
267 cbeb0b26 2006-04-01 devnull case 'p': /* pgp flag: encrypt, sign, or both */
268 7ce2007c 2006-02-12 devnull if(pgpopts(EARGF(usage())) < 0)
269 5cdb1798 2005-10-29 devnull sysfatal("bad pgp options");
270 5cdb1798 2005-10-29 devnull break;
271 5cdb1798 2005-10-29 devnull default:
272 5cdb1798 2005-10-29 devnull usage();
273 5cdb1798 2005-10-29 devnull break;
274 5cdb1798 2005-10-29 devnull }ARGEND;
275 5cdb1798 2005-10-29 devnull
276 5cdb1798 2005-10-29 devnull login = getlog();
277 5cdb1798 2005-10-29 devnull user = getenv("upasname");
278 5cdb1798 2005-10-29 devnull if(user == nil || *user == 0)
279 5cdb1798 2005-10-29 devnull user = login;
280 5cdb1798 2005-10-29 devnull if(user == nil || *user == 0)
281 5cdb1798 2005-10-29 devnull sysfatal("can't read user name");
282 5cdb1798 2005-10-29 devnull
283 5cdb1798 2005-10-29 devnull if(Binit(&in, 0, OREAD) < 0)
284 5cdb1798 2005-10-29 devnull sysfatal("can't Binit 0: %r");
285 5cdb1798 2005-10-29 devnull
286 5cdb1798 2005-10-29 devnull if(nflag && eightflag)
287 5cdb1798 2005-10-29 devnull sysfatal("can't use both -n and -8");
288 5cdb1798 2005-10-29 devnull if(eightflag && argc >= 1)
289 5cdb1798 2005-10-29 devnull usage();
290 5cdb1798 2005-10-29 devnull else if(!eightflag && argc < 1)
291 5cdb1798 2005-10-29 devnull usage();
292 5cdb1798 2005-10-29 devnull
293 5cdb1798 2005-10-29 devnull aliases = readaliases();
294 5cdb1798 2005-10-29 devnull if(!eightflag){
295 5cdb1798 2005-10-29 devnull to = expand(argc, argv);
296 5cdb1798 2005-10-29 devnull cc = expand(ccargc, ccargv);
297 5cdb1798 2005-10-29 devnull } else {
298 5cdb1798 2005-10-29 devnull to = nil;
299 5cdb1798 2005-10-29 devnull cc = nil;
300 5cdb1798 2005-10-29 devnull }
301 5cdb1798 2005-10-29 devnull
302 5cdb1798 2005-10-29 devnull flags = 0;
303 5cdb1798 2005-10-29 devnull headersrv = Nomessage;
304 5cdb1798 2005-10-29 devnull if(!nflag && !xflag && !lbflag &&!dflag) {
305 cbeb0b26 2006-04-01 devnull /* pass through headers, keeping track of which we've seen, */
306 cbeb0b26 2006-04-01 devnull /* perhaps building to list. */
307 5cdb1798 2005-10-29 devnull holding = holdon();
308 5cdb1798 2005-10-29 devnull headersrv = readheaders(&in, &flags, &hdrstring, eightflag ? &to : nil, 1);
309 5cdb1798 2005-10-29 devnull if(rfc822syntaxerror){
310 5cdb1798 2005-10-29 devnull Bdrain(&in);
311 5cdb1798 2005-10-29 devnull fatal("rfc822 syntax error, message not sent");
312 5cdb1798 2005-10-29 devnull }
313 5cdb1798 2005-10-29 devnull if(to == nil){
314 5cdb1798 2005-10-29 devnull Bdrain(&in);
315 5cdb1798 2005-10-29 devnull fatal("no addresses found, message not sent");
316 5cdb1798 2005-10-29 devnull }
317 5cdb1798 2005-10-29 devnull
318 5cdb1798 2005-10-29 devnull switch(headersrv){
319 cbeb0b26 2006-04-01 devnull case Error: /* error */
320 5cdb1798 2005-10-29 devnull fatal("reading");
321 5cdb1798 2005-10-29 devnull break;
322 cbeb0b26 2006-04-01 devnull case Nomessage: /* no message, just exit mimicking old behavior */
323 5cdb1798 2005-10-29 devnull noinput = 1;
324 5cdb1798 2005-10-29 devnull if(first == nil)
325 7ce2007c 2006-02-12 devnull threadexitsall(0);
326 5cdb1798 2005-10-29 devnull break;
327 5cdb1798 2005-10-29 devnull }
328 5cdb1798 2005-10-29 devnull }
329 5cdb1798 2005-10-29 devnull
330 5cdb1798 2005-10-29 devnull fd = sendmail(to, cc, &pid, Fflag ? argv[0] : nil);
331 5cdb1798 2005-10-29 devnull if(fd < 0)
332 5cdb1798 2005-10-29 devnull sysfatal("execing sendmail: %r\n:");
333 5cdb1798 2005-10-29 devnull if(xflag || lbflag || dflag){
334 5cdb1798 2005-10-29 devnull close(fd);
335 7ce2007c 2006-02-12 devnull threadexitsall(waitforsubprocs());
336 5cdb1798 2005-10-29 devnull }
337 5cdb1798 2005-10-29 devnull
338 5cdb1798 2005-10-29 devnull if(Binit(&out, fd, OWRITE) < 0)
339 5cdb1798 2005-10-29 devnull fatal("can't Binit 1: %r");
340 5cdb1798 2005-10-29 devnull
341 5cdb1798 2005-10-29 devnull if(!nflag){
342 5cdb1798 2005-10-29 devnull if(Bwrite(&out, s_to_c(hdrstring), s_len(hdrstring)) != s_len(hdrstring))
343 5cdb1798 2005-10-29 devnull fatal("write error");
344 5cdb1798 2005-10-29 devnull s_free(hdrstring);
345 5cdb1798 2005-10-29 devnull hdrstring = nil;
346 5cdb1798 2005-10-29 devnull
347 cbeb0b26 2006-04-01 devnull /* read user's standard headers */
348 5cdb1798 2005-10-29 devnull file = s_new();
349 5cdb1798 2005-10-29 devnull mboxpath("headers", user, file, 0);
350 5cdb1798 2005-10-29 devnull b = Bopen(s_to_c(file), OREAD);
351 5cdb1798 2005-10-29 devnull if(b != nil){
352 5cdb1798 2005-10-29 devnull switch(readheaders(b, &flags, &hdrstring, nil, 0)){
353 cbeb0b26 2006-04-01 devnull case Error: /* error */
354 5cdb1798 2005-10-29 devnull fatal("reading");
355 5cdb1798 2005-10-29 devnull }
356 5cdb1798 2005-10-29 devnull Bterm(b);
357 5cdb1798 2005-10-29 devnull if(Bwrite(&out, s_to_c(hdrstring), s_len(hdrstring)) != s_len(hdrstring))
358 5cdb1798 2005-10-29 devnull fatal("write error");
359 5cdb1798 2005-10-29 devnull s_free(hdrstring);
360 5cdb1798 2005-10-29 devnull hdrstring = nil;
361 5cdb1798 2005-10-29 devnull }
362 5cdb1798 2005-10-29 devnull }
363 5cdb1798 2005-10-29 devnull
364 cbeb0b26 2006-04-01 devnull /* add any headers we need */
365 5cdb1798 2005-10-29 devnull if((flags & (1<<Hdate)) == 0)
366 5cdb1798 2005-10-29 devnull if(printdate(&out) < 0)
367 5cdb1798 2005-10-29 devnull fatal("writing");
368 5cdb1798 2005-10-29 devnull if((flags & (1<<Hfrom)) == 0)
369 5cdb1798 2005-10-29 devnull if(printfrom(&out) < 0)
370 5cdb1798 2005-10-29 devnull fatal("writing");
371 5cdb1798 2005-10-29 devnull if((flags & (1<<Hto)) == 0)
372 5cdb1798 2005-10-29 devnull if(printto(&out, to) < 0)
373 5cdb1798 2005-10-29 devnull fatal("writing");
374 5cdb1798 2005-10-29 devnull if((flags & (1<<Hcc)) == 0)
375 5cdb1798 2005-10-29 devnull if(printcc(&out, cc) < 0)
376 5cdb1798 2005-10-29 devnull fatal("writing");
377 5cdb1798 2005-10-29 devnull if((flags & (1<<Hsubject)) == 0 && subject != nil)
378 5cdb1798 2005-10-29 devnull if(printsubject(&out, subject) < 0)
379 5cdb1798 2005-10-29 devnull fatal("writing");
380 5cdb1798 2005-10-29 devnull if(replymsg != nil)
381 7ce2007c 2006-02-12 devnull printinreplyto(&out, replymsg); /* ignore errors */
382 5cdb1798 2005-10-29 devnull Bprint(&out, "MIME-Version: 1.0\n");
383 5cdb1798 2005-10-29 devnull
384 cbeb0b26 2006-04-01 devnull if(pgpflag){ /* interpose pgp process between us and sendmail to handle body */
385 5cdb1798 2005-10-29 devnull Bflush(&out);
386 5cdb1798 2005-10-29 devnull Bterm(&out);
387 5cdb1798 2005-10-29 devnull fd = pgpfilter(&pgppid, fd, pgpflag);
388 5cdb1798 2005-10-29 devnull if(Binit(&out, fd, OWRITE) < 0)
389 5cdb1798 2005-10-29 devnull fatal("can't Binit 1: %r");
390 5cdb1798 2005-10-29 devnull }
391 5cdb1798 2005-10-29 devnull
392 cbeb0b26 2006-04-01 devnull /* if attachments, stick in multipart headers */
393 5cdb1798 2005-10-29 devnull boundary = nil;
394 5cdb1798 2005-10-29 devnull if(first != nil){
395 5cdb1798 2005-10-29 devnull boundary = mkboundary();
396 5cdb1798 2005-10-29 devnull Bprint(&out, "Content-Type: multipart/mixed;\n");
397 5cdb1798 2005-10-29 devnull Bprint(&out, "\tboundary=\"%s\"\n\n", boundary);
398 5cdb1798 2005-10-29 devnull Bprint(&out, "This is a multi-part message in MIME format.\n");
399 5cdb1798 2005-10-29 devnull Bprint(&out, "--%s\n", boundary);
400 5cdb1798 2005-10-29 devnull Bprint(&out, "Content-Disposition: inline\n");
401 5cdb1798 2005-10-29 devnull }
402 5cdb1798 2005-10-29 devnull
403 5cdb1798 2005-10-29 devnull if(!nflag){
404 5cdb1798 2005-10-29 devnull if(!noinput && headersrv == Ok){
405 5cdb1798 2005-10-29 devnull body(&in, &out, 1);
406 5cdb1798 2005-10-29 devnull }
407 5cdb1798 2005-10-29 devnull } else
408 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
409 5cdb1798 2005-10-29 devnull holdoff(holding);
410 5cdb1798 2005-10-29 devnull
411 5cdb1798 2005-10-29 devnull Bflush(&out);
412 5cdb1798 2005-10-29 devnull for(a = first; a != nil; a = a->next){
413 5cdb1798 2005-10-29 devnull if(lastchar != '\n')
414 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
415 5cdb1798 2005-10-29 devnull Bprint(&out, "--%s\n", boundary);
416 5cdb1798 2005-10-29 devnull attachment(a, &out);
417 5cdb1798 2005-10-29 devnull }
418 5cdb1798 2005-10-29 devnull
419 5cdb1798 2005-10-29 devnull if(first != nil){
420 5cdb1798 2005-10-29 devnull if(lastchar != '\n')
421 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
422 5cdb1798 2005-10-29 devnull Bprint(&out, "--%s--\n", boundary);
423 5cdb1798 2005-10-29 devnull }
424 5cdb1798 2005-10-29 devnull
425 5cdb1798 2005-10-29 devnull Bterm(&out);
426 5cdb1798 2005-10-29 devnull close(fd);
427 7ce2007c 2006-02-12 devnull threadexitsall(waitforsubprocs());
428 5cdb1798 2005-10-29 devnull }
429 5cdb1798 2005-10-29 devnull
430 cbeb0b26 2006-04-01 devnull /* evaluate pgp option string */
431 5cdb1798 2005-10-29 devnull int
432 5cdb1798 2005-10-29 devnull pgpopts(char *s)
433 5cdb1798 2005-10-29 devnull {
434 5cdb1798 2005-10-29 devnull if(s == nil || s[0] == '\0')
435 5cdb1798 2005-10-29 devnull return -1;
436 5cdb1798 2005-10-29 devnull while(*s){
437 5cdb1798 2005-10-29 devnull switch(*s++){
438 5cdb1798 2005-10-29 devnull case 's': case 'S':
439 5cdb1798 2005-10-29 devnull pgpflag |= PGPsign;
440 5cdb1798 2005-10-29 devnull break;
441 5cdb1798 2005-10-29 devnull case 'e': case 'E':
442 5cdb1798 2005-10-29 devnull pgpflag |= PGPencrypt;
443 5cdb1798 2005-10-29 devnull break;
444 5cdb1798 2005-10-29 devnull default:
445 5cdb1798 2005-10-29 devnull return -1;
446 5cdb1798 2005-10-29 devnull }
447 5cdb1798 2005-10-29 devnull }
448 5cdb1798 2005-10-29 devnull return 0;
449 5cdb1798 2005-10-29 devnull }
450 5cdb1798 2005-10-29 devnull
451 cbeb0b26 2006-04-01 devnull /* read headers from stdin into a String, expanding local aliases, */
452 cbeb0b26 2006-04-01 devnull /* keep track of which headers are there, which addresses we have */
453 cbeb0b26 2006-04-01 devnull /* remove Bcc: line. */
454 5cdb1798 2005-10-29 devnull int
455 5cdb1798 2005-10-29 devnull readheaders(Biobuf *in, int *fp, String **sp, Addr **top, int strict)
456 5cdb1798 2005-10-29 devnull {
457 5cdb1798 2005-10-29 devnull Addr *to;
458 5cdb1798 2005-10-29 devnull String *s, *sline;
459 5cdb1798 2005-10-29 devnull char *p;
460 5cdb1798 2005-10-29 devnull int i, seen, hdrtype;
461 5cdb1798 2005-10-29 devnull
462 5cdb1798 2005-10-29 devnull s = s_new();
463 5cdb1798 2005-10-29 devnull sline = nil;
464 5cdb1798 2005-10-29 devnull to = nil;
465 5cdb1798 2005-10-29 devnull hdrtype = -1;
466 5cdb1798 2005-10-29 devnull seen = 0;
467 5cdb1798 2005-10-29 devnull for(;;) {
468 5cdb1798 2005-10-29 devnull if((p = Brdline(in, '\n')) != nil) {
469 5cdb1798 2005-10-29 devnull seen = 1;
470 5cdb1798 2005-10-29 devnull p[Blinelen(in)-1] = 0;
471 5cdb1798 2005-10-29 devnull
472 cbeb0b26 2006-04-01 devnull /* coalesce multiline headers */
473 5cdb1798 2005-10-29 devnull if((*p == ' ' || *p == '\t') && sline){
474 5cdb1798 2005-10-29 devnull s_append(sline, "\n");
475 5cdb1798 2005-10-29 devnull s_append(sline, p);
476 5cdb1798 2005-10-29 devnull p[Blinelen(in)-1] = '\n';
477 5cdb1798 2005-10-29 devnull continue;
478 5cdb1798 2005-10-29 devnull }
479 5cdb1798 2005-10-29 devnull }
480 5cdb1798 2005-10-29 devnull
481 cbeb0b26 2006-04-01 devnull /* process the current header, it's all been read */
482 5cdb1798 2005-10-29 devnull if(sline) {
483 5cdb1798 2005-10-29 devnull assert(hdrtype != -1);
484 5cdb1798 2005-10-29 devnull if(top){
485 5cdb1798 2005-10-29 devnull switch(hdrtype){
486 5cdb1798 2005-10-29 devnull case Hto:
487 5cdb1798 2005-10-29 devnull case Hcc:
488 5cdb1798 2005-10-29 devnull case Hbcc:
489 5cdb1798 2005-10-29 devnull to = expandline(&sline, to);
490 5cdb1798 2005-10-29 devnull break;
491 5cdb1798 2005-10-29 devnull }
492 5cdb1798 2005-10-29 devnull }
493 3d038c32 2006-03-31 devnull if(hdrtype == Hsubject){
494 3d038c32 2006-03-31 devnull s_append(s, mksubject(s_to_c(sline)));
495 3d038c32 2006-03-31 devnull s_append(s, "\n");
496 3d038c32 2006-03-31 devnull }else if(top==nil || hdrtype!=Hbcc){
497 5cdb1798 2005-10-29 devnull s_append(s, s_to_c(sline));
498 5cdb1798 2005-10-29 devnull s_append(s, "\n");
499 5cdb1798 2005-10-29 devnull }
500 5cdb1798 2005-10-29 devnull s_free(sline);
501 5cdb1798 2005-10-29 devnull sline = nil;
502 5cdb1798 2005-10-29 devnull }
503 5cdb1798 2005-10-29 devnull
504 5cdb1798 2005-10-29 devnull if(p == nil)
505 5cdb1798 2005-10-29 devnull break;
506 5cdb1798 2005-10-29 devnull
507 cbeb0b26 2006-04-01 devnull /* if no :, it's not a header, seek back and break */
508 5cdb1798 2005-10-29 devnull if(strchr(p, ':') == nil){
509 5cdb1798 2005-10-29 devnull p[Blinelen(in)-1] = '\n';
510 5cdb1798 2005-10-29 devnull Bseek(in, -Blinelen(in), 1);
511 5cdb1798 2005-10-29 devnull break;
512 5cdb1798 2005-10-29 devnull }
513 5cdb1798 2005-10-29 devnull
514 5cdb1798 2005-10-29 devnull sline = s_copy(p);
515 5cdb1798 2005-10-29 devnull
516 cbeb0b26 2006-04-01 devnull /* classify the header. If we don't recognize it, break. This is */
517 cbeb0b26 2006-04-01 devnull /* to take care of user's that start messages with lines that contain */
518 cbeb0b26 2006-04-01 devnull /* ':'s but that aren't headers. This is a bit hokey. Since I decided */
519 cbeb0b26 2006-04-01 devnull /* to let users type headers, I need some way to distinguish. Therefore, */
520 cbeb0b26 2006-04-01 devnull /* marshal tries to know all likely headers and will indeed screw up if */
521 cbeb0b26 2006-04-01 devnull /* the user types an unlikely one. -- presotto */
522 5cdb1798 2005-10-29 devnull hdrtype = -1;
523 5cdb1798 2005-10-29 devnull for(i = 0; i < nelem(hdrs); i++){
524 5cdb1798 2005-10-29 devnull if(cistrncmp(hdrs[i], p, strlen(hdrs[i])) == 0){
525 5cdb1798 2005-10-29 devnull *fp |= 1<<i;
526 5cdb1798 2005-10-29 devnull hdrtype = i;
527 5cdb1798 2005-10-29 devnull break;
528 5cdb1798 2005-10-29 devnull }
529 5cdb1798 2005-10-29 devnull }
530 5cdb1798 2005-10-29 devnull if(strict){
531 5cdb1798 2005-10-29 devnull if(hdrtype == -1){
532 5cdb1798 2005-10-29 devnull p[Blinelen(in)-1] = '\n';
533 5cdb1798 2005-10-29 devnull Bseek(in, -Blinelen(in), 1);
534 5cdb1798 2005-10-29 devnull break;
535 5cdb1798 2005-10-29 devnull }
536 5cdb1798 2005-10-29 devnull } else
537 5cdb1798 2005-10-29 devnull hdrtype = 0;
538 5cdb1798 2005-10-29 devnull p[Blinelen(in)-1] = '\n';
539 5cdb1798 2005-10-29 devnull }
540 5cdb1798 2005-10-29 devnull
541 5cdb1798 2005-10-29 devnull *sp = s;
542 5cdb1798 2005-10-29 devnull if(top)
543 5cdb1798 2005-10-29 devnull *top = to;
544 5cdb1798 2005-10-29 devnull
545 5cdb1798 2005-10-29 devnull if(seen == 0){
546 5cdb1798 2005-10-29 devnull if(Blinelen(in) == 0)
547 5cdb1798 2005-10-29 devnull return Nomessage;
548 5cdb1798 2005-10-29 devnull else
549 5cdb1798 2005-10-29 devnull return Ok;
550 5cdb1798 2005-10-29 devnull }
551 5cdb1798 2005-10-29 devnull if(p == nil)
552 5cdb1798 2005-10-29 devnull return Nobody;
553 5cdb1798 2005-10-29 devnull return Ok;
554 5cdb1798 2005-10-29 devnull }
555 5cdb1798 2005-10-29 devnull
556 cbeb0b26 2006-04-01 devnull /* pass the body to sendmail, make sure body starts and ends with a newline */
557 5cdb1798 2005-10-29 devnull void
558 5cdb1798 2005-10-29 devnull body(Biobuf *in, Biobuf *out, int docontenttype)
559 5cdb1798 2005-10-29 devnull {
560 5cdb1798 2005-10-29 devnull char *buf, *p;
561 5cdb1798 2005-10-29 devnull int i, n, len;
562 5cdb1798 2005-10-29 devnull
563 5cdb1798 2005-10-29 devnull n = 0;
564 5cdb1798 2005-10-29 devnull len = 16*1024;
565 5cdb1798 2005-10-29 devnull buf = emalloc(len);
566 5cdb1798 2005-10-29 devnull
567 cbeb0b26 2006-04-01 devnull /* first char must be newline */
568 5cdb1798 2005-10-29 devnull i = Bgetc(in);
569 5cdb1798 2005-10-29 devnull if(i > 0){
570 5cdb1798 2005-10-29 devnull if(i != '\n')
571 5cdb1798 2005-10-29 devnull buf[n++] = '\n';
572 5cdb1798 2005-10-29 devnull buf[n++] = i;
573 5cdb1798 2005-10-29 devnull } else {
574 5cdb1798 2005-10-29 devnull buf[n++] = '\n';
575 5cdb1798 2005-10-29 devnull }
576 5cdb1798 2005-10-29 devnull
577 cbeb0b26 2006-04-01 devnull /* read into memory */
578 5cdb1798 2005-10-29 devnull if(docontenttype){
579 5cdb1798 2005-10-29 devnull while(docontenttype){
580 5cdb1798 2005-10-29 devnull if(n == len){
581 5cdb1798 2005-10-29 devnull len += len>>2;
582 5cdb1798 2005-10-29 devnull buf = realloc(buf, len);
583 5cdb1798 2005-10-29 devnull if(buf == nil)
584 5cdb1798 2005-10-29 devnull sysfatal("%r");
585 5cdb1798 2005-10-29 devnull }
586 5cdb1798 2005-10-29 devnull p = buf+n;
587 5cdb1798 2005-10-29 devnull i = Bread(in, p, len - n);
588 5cdb1798 2005-10-29 devnull if(i < 0)
589 5cdb1798 2005-10-29 devnull fatal("input error2");
590 5cdb1798 2005-10-29 devnull if(i == 0)
591 5cdb1798 2005-10-29 devnull break;
592 5cdb1798 2005-10-29 devnull n += i;
593 5cdb1798 2005-10-29 devnull for(; i > 0; i--)
594 5cdb1798 2005-10-29 devnull if((*p++ & 0x80) && docontenttype){
595 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Type: text/plain; charset=\"UTF-8\"\n");
596 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Transfer-Encoding: 8bit\n");
597 5cdb1798 2005-10-29 devnull docontenttype = 0;
598 5cdb1798 2005-10-29 devnull break;
599 5cdb1798 2005-10-29 devnull }
600 5cdb1798 2005-10-29 devnull }
601 5cdb1798 2005-10-29 devnull if(docontenttype){
602 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Type: text/plain; charset=\"US-ASCII\"\n");
603 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Transfer-Encoding: 7bit\n");
604 5cdb1798 2005-10-29 devnull }
605 5cdb1798 2005-10-29 devnull }
606 5cdb1798 2005-10-29 devnull
607 cbeb0b26 2006-04-01 devnull /* write what we already read */
608 5cdb1798 2005-10-29 devnull if(Bwrite(out, buf, n) < 0)
609 5cdb1798 2005-10-29 devnull fatal("output error");
610 5cdb1798 2005-10-29 devnull if(n > 0)
611 5cdb1798 2005-10-29 devnull lastchar = buf[n-1];
612 5cdb1798 2005-10-29 devnull else
613 5cdb1798 2005-10-29 devnull lastchar = '\n';
614 5cdb1798 2005-10-29 devnull
615 5cdb1798 2005-10-29 devnull
616 cbeb0b26 2006-04-01 devnull /* pass the rest */
617 5cdb1798 2005-10-29 devnull for(;;){
618 5cdb1798 2005-10-29 devnull n = Bread(in, buf, len);
619 5cdb1798 2005-10-29 devnull if(n < 0)
620 5cdb1798 2005-10-29 devnull fatal("input error2");
621 5cdb1798 2005-10-29 devnull if(n == 0)
622 5cdb1798 2005-10-29 devnull break;
623 5cdb1798 2005-10-29 devnull if(Bwrite(out, buf, n) < 0)
624 5cdb1798 2005-10-29 devnull fatal("output error");
625 5cdb1798 2005-10-29 devnull lastchar = buf[n-1];
626 5cdb1798 2005-10-29 devnull }
627 5cdb1798 2005-10-29 devnull }
628 5cdb1798 2005-10-29 devnull
629 cbeb0b26 2006-04-01 devnull /* pass the body to sendmail encoding with base64 */
630 cbeb0b26 2006-04-01 devnull /* */
631 cbeb0b26 2006-04-01 devnull /* the size of buf is very important to enc64. Anything other than */
632 cbeb0b26 2006-04-01 devnull /* a multiple of 3 will cause enc64 to output a termination sequence. */
633 cbeb0b26 2006-04-01 devnull /* To ensure that a full buf corresponds to a multiple of complete lines, */
634 cbeb0b26 2006-04-01 devnull /* we make buf a multiple of 3*18 since that's how many enc64 sticks on */
635 cbeb0b26 2006-04-01 devnull /* a single line. This avoids short lines in the output which is pleasing */
636 cbeb0b26 2006-04-01 devnull /* but not necessary. */
637 cbeb0b26 2006-04-01 devnull /* */
638 5cdb1798 2005-10-29 devnull void
639 5cdb1798 2005-10-29 devnull body64(Biobuf *in, Biobuf *out)
640 5cdb1798 2005-10-29 devnull {
641 5cdb1798 2005-10-29 devnull uchar buf[3*18*54];
642 5cdb1798 2005-10-29 devnull char obuf[3*18*54*2];
643 5cdb1798 2005-10-29 devnull int m, n;
644 5cdb1798 2005-10-29 devnull
645 5cdb1798 2005-10-29 devnull Bprint(out, "\n");
646 5cdb1798 2005-10-29 devnull for(;;){
647 5cdb1798 2005-10-29 devnull n = Bread(in, buf, sizeof(buf));
648 5cdb1798 2005-10-29 devnull if(n < 0)
649 5cdb1798 2005-10-29 devnull fatal("input error");
650 5cdb1798 2005-10-29 devnull if(n == 0)
651 5cdb1798 2005-10-29 devnull break;
652 5cdb1798 2005-10-29 devnull m = enc64(obuf, sizeof(obuf), buf, n);
653 5cdb1798 2005-10-29 devnull if((n=Bwrite(out, obuf, m)) < 0)
654 5cdb1798 2005-10-29 devnull fatal("output error");
655 5cdb1798 2005-10-29 devnull }
656 5cdb1798 2005-10-29 devnull lastchar = '\n';
657 5cdb1798 2005-10-29 devnull }
658 5cdb1798 2005-10-29 devnull
659 cbeb0b26 2006-04-01 devnull /* pass message to sendmail, make sure body starts with a newline */
660 5cdb1798 2005-10-29 devnull void
661 5cdb1798 2005-10-29 devnull copy(Biobuf *in, Biobuf *out)
662 5cdb1798 2005-10-29 devnull {
663 5cdb1798 2005-10-29 devnull char buf[4*1024];
664 5cdb1798 2005-10-29 devnull int n;
665 5cdb1798 2005-10-29 devnull
666 5cdb1798 2005-10-29 devnull for(;;){
667 5cdb1798 2005-10-29 devnull n = Bread(in, buf, sizeof(buf));
668 5cdb1798 2005-10-29 devnull if(n < 0)
669 5cdb1798 2005-10-29 devnull fatal("input error");
670 5cdb1798 2005-10-29 devnull if(n == 0)
671 5cdb1798 2005-10-29 devnull break;
672 5cdb1798 2005-10-29 devnull if(Bwrite(out, buf, n) < 0)
673 5cdb1798 2005-10-29 devnull fatal("output error");
674 5cdb1798 2005-10-29 devnull }
675 5cdb1798 2005-10-29 devnull }
676 5cdb1798 2005-10-29 devnull
677 5cdb1798 2005-10-29 devnull void
678 5cdb1798 2005-10-29 devnull attachment(Attach *a, Biobuf *out)
679 5cdb1798 2005-10-29 devnull {
680 5cdb1798 2005-10-29 devnull Biobuf *f;
681 5cdb1798 2005-10-29 devnull char *p;
682 5cdb1798 2005-10-29 devnull
683 7ce2007c 2006-02-12 devnull f = emalloc(sizeof *f);
684 7ce2007c 2006-02-12 devnull Binit(f, a->fd, OREAD);
685 cbeb0b26 2006-04-01 devnull /* if it's already mime encoded, just copy */
686 5cdb1798 2005-10-29 devnull if(strcmp(a->type, "mime") == 0){
687 5cdb1798 2005-10-29 devnull copy(f, out);
688 5cdb1798 2005-10-29 devnull Bterm(f);
689 7ce2007c 2006-02-12 devnull free(f);
690 7ce2007c 2006-02-12 devnull return;
691 5cdb1798 2005-10-29 devnull }
692 5cdb1798 2005-10-29 devnull
693 cbeb0b26 2006-04-01 devnull /* if it's not already mime encoded ... */
694 5cdb1798 2005-10-29 devnull if(strcmp(a->type, "text/plain") != 0)
695 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Type: %s\n", a->type);
696 5cdb1798 2005-10-29 devnull
697 b5f65921 2006-02-11 devnull if(a->inline){
698 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Disposition: inline\n");
699 5cdb1798 2005-10-29 devnull } else {
700 5cdb1798 2005-10-29 devnull p = strrchr(a->path, '/');
701 5cdb1798 2005-10-29 devnull if(p == nil)
702 5cdb1798 2005-10-29 devnull p = a->path;
703 5cdb1798 2005-10-29 devnull else
704 5cdb1798 2005-10-29 devnull p++;
705 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Disposition: attachment; filename=%Z\n", p);
706 5cdb1798 2005-10-29 devnull }
707 5cdb1798 2005-10-29 devnull
708 5cdb1798 2005-10-29 devnull /* dump our local 'From ' line when passing along mail messages */
709 5cdb1798 2005-10-29 devnull if(strcmp(a->type, "message/rfc822") == 0){
710 5cdb1798 2005-10-29 devnull p = Brdline(f, '\n');
711 5cdb1798 2005-10-29 devnull if(strncmp(p, "From ", 5) != 0)
712 5cdb1798 2005-10-29 devnull Bseek(f, 0, 0);
713 5cdb1798 2005-10-29 devnull }
714 5cdb1798 2005-10-29 devnull if(a->ctype->display){
715 5cdb1798 2005-10-29 devnull body(f, out, strcmp(a->type, "text/plain") == 0);
716 5cdb1798 2005-10-29 devnull } else {
717 5cdb1798 2005-10-29 devnull Bprint(out, "Content-Transfer-Encoding: base64\n");
718 5cdb1798 2005-10-29 devnull body64(f, out);
719 5cdb1798 2005-10-29 devnull }
720 5cdb1798 2005-10-29 devnull Bterm(f);
721 7ce2007c 2006-02-12 devnull free(f);
722 5cdb1798 2005-10-29 devnull }
723 5cdb1798 2005-10-29 devnull
724 5cdb1798 2005-10-29 devnull char *ascwday[] =
725 5cdb1798 2005-10-29 devnull {
726 5cdb1798 2005-10-29 devnull "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
727 5cdb1798 2005-10-29 devnull };
728 5cdb1798 2005-10-29 devnull
729 5cdb1798 2005-10-29 devnull char *ascmon[] =
730 5cdb1798 2005-10-29 devnull {
731 5cdb1798 2005-10-29 devnull "Jan", "Feb", "Mar", "Apr", "May", "Jun",
732 5cdb1798 2005-10-29 devnull "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
733 5cdb1798 2005-10-29 devnull };
734 5cdb1798 2005-10-29 devnull
735 5cdb1798 2005-10-29 devnull int
736 5cdb1798 2005-10-29 devnull printdate(Biobuf *b)
737 5cdb1798 2005-10-29 devnull {
738 5cdb1798 2005-10-29 devnull Tm *tm;
739 5cdb1798 2005-10-29 devnull int tz;
740 5cdb1798 2005-10-29 devnull
741 5cdb1798 2005-10-29 devnull tm = localtime(time(0));
742 5cdb1798 2005-10-29 devnull tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60);
743 5cdb1798 2005-10-29 devnull
744 5cdb1798 2005-10-29 devnull return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n",
745 5cdb1798 2005-10-29 devnull ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900+tm->year,
746 5cdb1798 2005-10-29 devnull tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);
747 5cdb1798 2005-10-29 devnull }
748 5cdb1798 2005-10-29 devnull
749 5cdb1798 2005-10-29 devnull int
750 5cdb1798 2005-10-29 devnull printfrom(Biobuf *b)
751 5cdb1798 2005-10-29 devnull {
752 5cdb1798 2005-10-29 devnull return Bprint(b, "From: %s\n", user);
753 5cdb1798 2005-10-29 devnull }
754 5cdb1798 2005-10-29 devnull
755 5cdb1798 2005-10-29 devnull int
756 5cdb1798 2005-10-29 devnull printto(Biobuf *b, Addr *a)
757 5cdb1798 2005-10-29 devnull {
758 5cdb1798 2005-10-29 devnull int i;
759 5cdb1798 2005-10-29 devnull
760 5cdb1798 2005-10-29 devnull if(Bprint(b, "To: %s", a->v) < 0)
761 5cdb1798 2005-10-29 devnull return -1;
762 5cdb1798 2005-10-29 devnull i = 0;
763 5cdb1798 2005-10-29 devnull for(a = a->next; a != nil; a = a->next)
764 5cdb1798 2005-10-29 devnull if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)
765 5cdb1798 2005-10-29 devnull return -1;
766 5cdb1798 2005-10-29 devnull if(Bprint(b, "\n") < 0)
767 5cdb1798 2005-10-29 devnull return -1;
768 5cdb1798 2005-10-29 devnull return 0;
769 5cdb1798 2005-10-29 devnull }
770 5cdb1798 2005-10-29 devnull
771 5cdb1798 2005-10-29 devnull int
772 5cdb1798 2005-10-29 devnull printcc(Biobuf *b, Addr *a)
773 5cdb1798 2005-10-29 devnull {
774 5cdb1798 2005-10-29 devnull int i;
775 5cdb1798 2005-10-29 devnull
776 5cdb1798 2005-10-29 devnull if(a == nil)
777 5cdb1798 2005-10-29 devnull return 0;
778 5cdb1798 2005-10-29 devnull if(Bprint(b, "CC: %s", a->v) < 0)
779 5cdb1798 2005-10-29 devnull return -1;
780 5cdb1798 2005-10-29 devnull i = 0;
781 5cdb1798 2005-10-29 devnull for(a = a->next; a != nil; a = a->next)
782 5cdb1798 2005-10-29 devnull if(Bprint(b, "%s%s", ((i++ & 7) == 7)?",\n\t":", ", a->v) < 0)
783 5cdb1798 2005-10-29 devnull return -1;
784 5cdb1798 2005-10-29 devnull if(Bprint(b, "\n") < 0)
785 5cdb1798 2005-10-29 devnull return -1;
786 5cdb1798 2005-10-29 devnull return 0;
787 5cdb1798 2005-10-29 devnull }
788 5cdb1798 2005-10-29 devnull
789 5cdb1798 2005-10-29 devnull int
790 5cdb1798 2005-10-29 devnull printsubject(Biobuf *b, char *subject)
791 5cdb1798 2005-10-29 devnull {
792 5cdb1798 2005-10-29 devnull return Bprint(b, "Subject: %s\n", subject);
793 5cdb1798 2005-10-29 devnull }
794 5cdb1798 2005-10-29 devnull
795 5cdb1798 2005-10-29 devnull int
796 5cdb1798 2005-10-29 devnull printinreplyto(Biobuf *out, char *dir)
797 5cdb1798 2005-10-29 devnull {
798 7ce2007c 2006-02-12 devnull String *s;
799 5cdb1798 2005-10-29 devnull char buf[256];
800 5cdb1798 2005-10-29 devnull int fd;
801 5cdb1798 2005-10-29 devnull int n;
802 5cdb1798 2005-10-29 devnull
803 7ce2007c 2006-02-12 devnull if(mountmail() < 0)
804 7ce2007c 2006-02-12 devnull return -1;
805 7ce2007c 2006-02-12 devnull if(strncmp(dir, "Mail/", 5) != 0)
806 7ce2007c 2006-02-12 devnull return -1;
807 7ce2007c 2006-02-12 devnull s = s_copy(dir+5);
808 5cdb1798 2005-10-29 devnull s_append(s, "/messageid");
809 7ce2007c 2006-02-12 devnull fd = fsopenfd(mailfs, s_to_c(s), OREAD);
810 5cdb1798 2005-10-29 devnull s_free(s);
811 5cdb1798 2005-10-29 devnull if(fd < 0)
812 7ce2007c 2006-02-12 devnull return -1;
813 7ce2007c 2006-02-12 devnull n = readn(fd, buf, sizeof(buf)-1);
814 5cdb1798 2005-10-29 devnull close(fd);
815 5cdb1798 2005-10-29 devnull if(n <= 0)
816 7ce2007c 2006-02-12 devnull return -1;
817 5cdb1798 2005-10-29 devnull buf[n] = 0;
818 5cdb1798 2005-10-29 devnull return Bprint(out, "In-Reply-To: %s\n", buf);
819 0df4c01e 2006-02-14 devnull }
820 0df4c01e 2006-02-14 devnull
821 0df4c01e 2006-02-14 devnull int
822 0df4c01e 2006-02-14 devnull mopen(char *file, int mode)
823 0df4c01e 2006-02-14 devnull {
824 0df4c01e 2006-02-14 devnull int fd;
825 0df4c01e 2006-02-14 devnull
826 0df4c01e 2006-02-14 devnull if((fd = open(file, mode)) >= 0)
827 0df4c01e 2006-02-14 devnull return fd;
828 0df4c01e 2006-02-14 devnull if(strncmp(file, "Mail/", 5) == 0 && mountmail() >= 0 && (fd = fsopenfd(mailfs, file+5, mode)) >= 0)
829 0df4c01e 2006-02-14 devnull return fd;
830 0df4c01e 2006-02-14 devnull return -1;
831 5cdb1798 2005-10-29 devnull }
832 5cdb1798 2005-10-29 devnull
833 5cdb1798 2005-10-29 devnull Attach*
834 b5f65921 2006-02-11 devnull mkattach(char *file, char *type, int inline)
835 5cdb1798 2005-10-29 devnull {
836 5cdb1798 2005-10-29 devnull Ctype *c;
837 5cdb1798 2005-10-29 devnull Attach *a;
838 5cdb1798 2005-10-29 devnull char ftype[64];
839 5cdb1798 2005-10-29 devnull char *p;
840 7ce2007c 2006-02-12 devnull int fd, n, pfd[2], xfd[3];
841 5cdb1798 2005-10-29 devnull
842 5cdb1798 2005-10-29 devnull if(file == nil)
843 5cdb1798 2005-10-29 devnull return nil;
844 0df4c01e 2006-02-14 devnull if((fd = mopen(file, OREAD)) < 0)
845 5cdb1798 2005-10-29 devnull return nil;
846 5cdb1798 2005-10-29 devnull a = emalloc(sizeof(*a));
847 7ce2007c 2006-02-12 devnull a->fd = fd;
848 5cdb1798 2005-10-29 devnull a->path = file;
849 5cdb1798 2005-10-29 devnull a->next = nil;
850 5cdb1798 2005-10-29 devnull a->type = type;
851 b5f65921 2006-02-11 devnull a->inline = inline;
852 5cdb1798 2005-10-29 devnull a->ctype = nil;
853 5cdb1798 2005-10-29 devnull if(type != nil){
854 5cdb1798 2005-10-29 devnull for(c = ctype; ; c++)
855 5cdb1798 2005-10-29 devnull if(strncmp(type, c->type, strlen(c->type)) == 0){
856 5cdb1798 2005-10-29 devnull a->ctype = c;
857 5cdb1798 2005-10-29 devnull break;
858 5cdb1798 2005-10-29 devnull }
859 5cdb1798 2005-10-29 devnull return a;
860 5cdb1798 2005-10-29 devnull }
861 5cdb1798 2005-10-29 devnull
862 cbeb0b26 2006-04-01 devnull /* pick a type depending on extension */
863 5cdb1798 2005-10-29 devnull p = strchr(file, '.');
864 5cdb1798 2005-10-29 devnull if(p != nil)
865 5cdb1798 2005-10-29 devnull p++;
866 5cdb1798 2005-10-29 devnull
867 cbeb0b26 2006-04-01 devnull /* check the builtin extensions */
868 5cdb1798 2005-10-29 devnull if(p != nil){
869 5cdb1798 2005-10-29 devnull for(c = ctype; c->ext != nil; c++)
870 5cdb1798 2005-10-29 devnull if(strcmp(p, c->ext) == 0){
871 5cdb1798 2005-10-29 devnull a->type = c->type;
872 5cdb1798 2005-10-29 devnull a->ctype = c;
873 5cdb1798 2005-10-29 devnull return a;
874 5cdb1798 2005-10-29 devnull }
875 5cdb1798 2005-10-29 devnull }
876 5cdb1798 2005-10-29 devnull
877 cbeb0b26 2006-04-01 devnull /* try the mime types file */
878 5cdb1798 2005-10-29 devnull if(p != nil){
879 5cdb1798 2005-10-29 devnull if(mimetypes == nil)
880 5cdb1798 2005-10-29 devnull readmimetypes();
881 5cdb1798 2005-10-29 devnull for(c = mimetypes; c != nil && c->ext != nil; c++)
882 5cdb1798 2005-10-29 devnull if(strcmp(p, c->ext) == 0){
883 5cdb1798 2005-10-29 devnull a->type = c->type;
884 5cdb1798 2005-10-29 devnull a->ctype = c;
885 5cdb1798 2005-10-29 devnull return a;
886 5cdb1798 2005-10-29 devnull }
887 5cdb1798 2005-10-29 devnull }
888 5cdb1798 2005-10-29 devnull
889 cbeb0b26 2006-04-01 devnull /* run file to figure out the type */
890 cbeb0b26 2006-04-01 devnull a->type = "application/octet-stream"; /* safest default */
891 5cdb1798 2005-10-29 devnull if(pipe(pfd) < 0)
892 5cdb1798 2005-10-29 devnull return a;
893 7ce2007c 2006-02-12 devnull
894 0df4c01e 2006-02-14 devnull xfd[0] = mopen(file, OREAD);
895 7ce2007c 2006-02-12 devnull xfd[1] = pfd[0];
896 7ce2007c 2006-02-12 devnull xfd[2] = dup(2, -1);
897 0df4c01e 2006-02-14 devnull if((pid=threadspawnl(xfd, unsharp("#9/bin/file"), "file", "-m", nil)) < 0){
898 7ce2007c 2006-02-12 devnull close(xfd[0]);
899 0df4c01e 2006-02-14 devnull close(xfd[1]);
900 7ce2007c 2006-02-12 devnull close(xfd[2]);
901 7ce2007c 2006-02-12 devnull return a;
902 5cdb1798 2005-10-29 devnull }
903 7ce2007c 2006-02-12 devnull /* threadspawnl closed pfd[0] */
904 5cdb1798 2005-10-29 devnull
905 7ce2007c 2006-02-12 devnull n = readn(pfd[1], ftype, sizeof(ftype));
906 7ce2007c 2006-02-12 devnull if(n > 0){
907 7ce2007c 2006-02-12 devnull ftype[n-1] = 0;
908 7ce2007c 2006-02-12 devnull a->type = estrdup(ftype);
909 7ce2007c 2006-02-12 devnull }
910 7ce2007c 2006-02-12 devnull close(pfd[1]);
911 7ce2007c 2006-02-12 devnull procwait(pid);
912 7ce2007c 2006-02-12 devnull
913 5cdb1798 2005-10-29 devnull for(c = ctype; ; c++)
914 5cdb1798 2005-10-29 devnull if(strncmp(a->type, c->type, strlen(c->type)) == 0){
915 5cdb1798 2005-10-29 devnull a->ctype = c;
916 5cdb1798 2005-10-29 devnull break;
917 5cdb1798 2005-10-29 devnull }
918 5cdb1798 2005-10-29 devnull
919 5cdb1798 2005-10-29 devnull return a;
920 5cdb1798 2005-10-29 devnull }
921 5cdb1798 2005-10-29 devnull
922 5cdb1798 2005-10-29 devnull char*
923 5cdb1798 2005-10-29 devnull mkboundary(void)
924 5cdb1798 2005-10-29 devnull {
925 5cdb1798 2005-10-29 devnull char buf[32];
926 5cdb1798 2005-10-29 devnull int i;
927 5cdb1798 2005-10-29 devnull
928 5cdb1798 2005-10-29 devnull srand((time(0)<<16)|getpid());
929 5cdb1798 2005-10-29 devnull strcpy(buf, "upas-");
930 5cdb1798 2005-10-29 devnull for(i = 5; i < sizeof(buf)-1; i++)
931 5cdb1798 2005-10-29 devnull buf[i] = 'a' + nrand(26);
932 5cdb1798 2005-10-29 devnull buf[i] = 0;
933 5cdb1798 2005-10-29 devnull return estrdup(buf);
934 5cdb1798 2005-10-29 devnull }
935 5cdb1798 2005-10-29 devnull
936 cbeb0b26 2006-04-01 devnull /* copy types to two fd's */
937 5cdb1798 2005-10-29 devnull static void
938 5cdb1798 2005-10-29 devnull tee(int in, int out1, int out2)
939 5cdb1798 2005-10-29 devnull {
940 5cdb1798 2005-10-29 devnull char buf[8*1024];
941 5cdb1798 2005-10-29 devnull int n;
942 5cdb1798 2005-10-29 devnull
943 5cdb1798 2005-10-29 devnull for(;;){
944 5cdb1798 2005-10-29 devnull n = read(in, buf, sizeof(buf));
945 5cdb1798 2005-10-29 devnull if(n <= 0)
946 5cdb1798 2005-10-29 devnull break;
947 5cdb1798 2005-10-29 devnull if(write(out1, buf, n) < 0)
948 5cdb1798 2005-10-29 devnull break;
949 5cdb1798 2005-10-29 devnull if(write(out2, buf, n) < 0)
950 5cdb1798 2005-10-29 devnull break;
951 5cdb1798 2005-10-29 devnull }
952 7ce2007c 2006-02-12 devnull }
953 7ce2007c 2006-02-12 devnull
954 7ce2007c 2006-02-12 devnull static void
955 7ce2007c 2006-02-12 devnull teeproc(void *v)
956 7ce2007c 2006-02-12 devnull {
957 7ce2007c 2006-02-12 devnull int *a;
958 7ce2007c 2006-02-12 devnull
959 7ce2007c 2006-02-12 devnull a = v;
960 7ce2007c 2006-02-12 devnull tee(a[0], a[1], a[2]);
961 7ce2007c 2006-02-12 devnull write(a[2], "\n", 1);
962 5cdb1798 2005-10-29 devnull }
963 5cdb1798 2005-10-29 devnull
964 cbeb0b26 2006-04-01 devnull /* print the unix from line */
965 5cdb1798 2005-10-29 devnull int
966 5cdb1798 2005-10-29 devnull printunixfrom(int fd)
967 5cdb1798 2005-10-29 devnull {
968 5cdb1798 2005-10-29 devnull Tm *tm;
969 5cdb1798 2005-10-29 devnull int tz;
970 5cdb1798 2005-10-29 devnull
971 5cdb1798 2005-10-29 devnull tm = localtime(time(0));
972 5cdb1798 2005-10-29 devnull tz = (tm->tzoff/3600)*100 + ((tm->tzoff/60)%60);
973 5cdb1798 2005-10-29 devnull
974 5cdb1798 2005-10-29 devnull return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n",
975 5cdb1798 2005-10-29 devnull user,
976 5cdb1798 2005-10-29 devnull ascwday[tm->wday], ascmon[tm->mon], tm->mday,
977 5cdb1798 2005-10-29 devnull tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900+tm->year);
978 5cdb1798 2005-10-29 devnull }
979 5cdb1798 2005-10-29 devnull
980 5cdb1798 2005-10-29 devnull char *specialfile[] =
981 5cdb1798 2005-10-29 devnull {
982 5cdb1798 2005-10-29 devnull "pipeto",
983 5cdb1798 2005-10-29 devnull "pipefrom",
984 5cdb1798 2005-10-29 devnull "L.mbox",
985 5cdb1798 2005-10-29 devnull "forward",
986 5cdb1798 2005-10-29 devnull "names"
987 5cdb1798 2005-10-29 devnull };
988 5cdb1798 2005-10-29 devnull
989 cbeb0b26 2006-04-01 devnull /* return 1 if this is a special file */
990 5cdb1798 2005-10-29 devnull static int
991 5cdb1798 2005-10-29 devnull special(String *s)
992 5cdb1798 2005-10-29 devnull {
993 5cdb1798 2005-10-29 devnull char *p;
994 5cdb1798 2005-10-29 devnull int i;
995 5cdb1798 2005-10-29 devnull
996 5cdb1798 2005-10-29 devnull p = strrchr(s_to_c(s), '/');
997 5cdb1798 2005-10-29 devnull if(p == nil)
998 5cdb1798 2005-10-29 devnull p = s_to_c(s);
999 5cdb1798 2005-10-29 devnull else
1000 5cdb1798 2005-10-29 devnull p++;
1001 5cdb1798 2005-10-29 devnull for(i = 0; i < nelem(specialfile); i++)
1002 5cdb1798 2005-10-29 devnull if(strcmp(p, specialfile[i]) == 0)
1003 5cdb1798 2005-10-29 devnull return 1;
1004 5cdb1798 2005-10-29 devnull return 0;
1005 5cdb1798 2005-10-29 devnull }
1006 5cdb1798 2005-10-29 devnull
1007 cbeb0b26 2006-04-01 devnull /* open the folder using the recipients account name */
1008 5cdb1798 2005-10-29 devnull static int
1009 5cdb1798 2005-10-29 devnull openfolder(char *rcvr)
1010 5cdb1798 2005-10-29 devnull {
1011 5cdb1798 2005-10-29 devnull char *p;
1012 5cdb1798 2005-10-29 devnull int c;
1013 5cdb1798 2005-10-29 devnull String *file;
1014 5cdb1798 2005-10-29 devnull Dir *d;
1015 5cdb1798 2005-10-29 devnull int fd;
1016 5cdb1798 2005-10-29 devnull int scarey;
1017 5cdb1798 2005-10-29 devnull
1018 5cdb1798 2005-10-29 devnull file = s_new();
1019 5cdb1798 2005-10-29 devnull mboxpath("f", user, file, 0);
1020 5cdb1798 2005-10-29 devnull
1021 cbeb0b26 2006-04-01 devnull /* if $mail/f exists, store there, otherwise in $mail */
1022 5cdb1798 2005-10-29 devnull d = dirstat(s_to_c(file));
1023 5cdb1798 2005-10-29 devnull if(d == nil || d->qid.type != QTDIR){
1024 5cdb1798 2005-10-29 devnull scarey = 1;
1025 5cdb1798 2005-10-29 devnull file->ptr -= 1;
1026 5cdb1798 2005-10-29 devnull } else {
1027 5cdb1798 2005-10-29 devnull s_putc(file, '/');
1028 5cdb1798 2005-10-29 devnull scarey = 0;
1029 5cdb1798 2005-10-29 devnull }
1030 5cdb1798 2005-10-29 devnull free(d);
1031 5cdb1798 2005-10-29 devnull
1032 5cdb1798 2005-10-29 devnull p = strrchr(rcvr, '!');
1033 5cdb1798 2005-10-29 devnull if(p != nil)
1034 5cdb1798 2005-10-29 devnull rcvr = p+1;
1035 5cdb1798 2005-10-29 devnull
1036 5cdb1798 2005-10-29 devnull while(*rcvr && *rcvr != '@'){
1037 5cdb1798 2005-10-29 devnull c = *rcvr++;
1038 5cdb1798 2005-10-29 devnull if(c == '/')
1039 5cdb1798 2005-10-29 devnull c = '_';
1040 5cdb1798 2005-10-29 devnull s_putc(file, c);
1041 5cdb1798 2005-10-29 devnull }
1042 5cdb1798 2005-10-29 devnull s_terminate(file);
1043 5cdb1798 2005-10-29 devnull
1044 5cdb1798 2005-10-29 devnull if(scarey && special(file)){
1045 5cdb1798 2005-10-29 devnull fprint(2, "%s: won't overwrite %s\n", argv0, s_to_c(file));
1046 5cdb1798 2005-10-29 devnull s_free(file);
1047 5cdb1798 2005-10-29 devnull return -1;
1048 5cdb1798 2005-10-29 devnull }
1049 5cdb1798 2005-10-29 devnull
1050 5cdb1798 2005-10-29 devnull fd = open(s_to_c(file), OWRITE);
1051 5cdb1798 2005-10-29 devnull if(fd < 0)
1052 5cdb1798 2005-10-29 devnull fd = create(s_to_c(file), OWRITE, 0660);
1053 5cdb1798 2005-10-29 devnull
1054 5cdb1798 2005-10-29 devnull s_free(file);
1055 5cdb1798 2005-10-29 devnull return fd;
1056 5cdb1798 2005-10-29 devnull }
1057 5cdb1798 2005-10-29 devnull
1058 cbeb0b26 2006-04-01 devnull /* start up sendmail and return an fd to talk to it with */
1059 5cdb1798 2005-10-29 devnull int
1060 5cdb1798 2005-10-29 devnull sendmail(Addr *to, Addr *cc, int *pid, char *rcvr)
1061 5cdb1798 2005-10-29 devnull {
1062 5cdb1798 2005-10-29 devnull char **av, **v;
1063 7ce2007c 2006-02-12 devnull int ac, fd, *targ;
1064 7ce2007c 2006-02-12 devnull int pfd[2], sfd, xfd[3];
1065 5cdb1798 2005-10-29 devnull String *cmd;
1066 7ce2007c 2006-02-12 devnull char *x;
1067 5cdb1798 2005-10-29 devnull Addr *a;
1068 5cdb1798 2005-10-29 devnull
1069 5cdb1798 2005-10-29 devnull fd = -1;
1070 5cdb1798 2005-10-29 devnull if(rcvr != nil)
1071 5cdb1798 2005-10-29 devnull fd = openfolder(rcvr);
1072 5cdb1798 2005-10-29 devnull
1073 5cdb1798 2005-10-29 devnull ac = 0;
1074 5cdb1798 2005-10-29 devnull for(a = to; a != nil; a = a->next)
1075 5cdb1798 2005-10-29 devnull ac++;
1076 5cdb1798 2005-10-29 devnull for(a = cc; a != nil; a = a->next)
1077 5cdb1798 2005-10-29 devnull ac++;
1078 5cdb1798 2005-10-29 devnull v = av = emalloc(sizeof(char*)*(ac+20));
1079 5cdb1798 2005-10-29 devnull ac = 0;
1080 5cdb1798 2005-10-29 devnull v[ac++] = "sendmail";
1081 5cdb1798 2005-10-29 devnull if(xflag)
1082 5cdb1798 2005-10-29 devnull v[ac++] = "-x";
1083 5cdb1798 2005-10-29 devnull if(rflag)
1084 5cdb1798 2005-10-29 devnull v[ac++] = "-r";
1085 5cdb1798 2005-10-29 devnull if(lbflag)
1086 5cdb1798 2005-10-29 devnull v[ac++] = "-#";
1087 5cdb1798 2005-10-29 devnull if(dflag)
1088 5cdb1798 2005-10-29 devnull v[ac++] = "-d";
1089 5cdb1798 2005-10-29 devnull for(a = to; a != nil; a = a->next)
1090 5cdb1798 2005-10-29 devnull v[ac++] = a->v;
1091 5cdb1798 2005-10-29 devnull for(a = cc; a != nil; a = a->next)
1092 5cdb1798 2005-10-29 devnull v[ac++] = a->v;
1093 5cdb1798 2005-10-29 devnull v[ac] = 0;
1094 5cdb1798 2005-10-29 devnull
1095 5cdb1798 2005-10-29 devnull if(pipe(pfd) < 0)
1096 7ce2007c 2006-02-12 devnull fatal("pipe: %r");
1097 7ce2007c 2006-02-12 devnull
1098 7ce2007c 2006-02-12 devnull xfd[0] = pfd[0];
1099 7ce2007c 2006-02-12 devnull xfd[1] = dup(1, -1);
1100 7ce2007c 2006-02-12 devnull xfd[2] = dup(2, -1);
1101 5cdb1798 2005-10-29 devnull
1102 7ce2007c 2006-02-12 devnull if(replymsg != nil)
1103 7ce2007c 2006-02-12 devnull putenv("replymsg", replymsg);
1104 7ce2007c 2006-02-12 devnull cmd = mboxpath("pipefrom", login, s_new(), 0);
1105 5cdb1798 2005-10-29 devnull
1106 7ce2007c 2006-02-12 devnull if((*pid = threadspawn(xfd, x=s_to_c(cmd), av)) < 0
1107 7ce2007c 2006-02-12 devnull && (*pid = threadspawn(xfd, x="myupassend", av)) < 0
1108 7ce2007c 2006-02-12 devnull && (*pid = threadspawn(xfd, x=unsharp("#9/bin/upas/send"), av)) < 0)
1109 5cc53af9 2006-02-12 devnull fatal("exec: %r");
1110 7ce2007c 2006-02-12 devnull /* threadspawn closed pfd[0] (== xfd[0]) */
1111 7ce2007c 2006-02-12 devnull sfd = pfd[1];
1112 7ce2007c 2006-02-12 devnull
1113 7ce2007c 2006-02-12 devnull if(rcvr != nil){
1114 7ce2007c 2006-02-12 devnull if(pipe(pfd) < 0)
1115 7ce2007c 2006-02-12 devnull fatal("pipe: %r");
1116 7ce2007c 2006-02-12 devnull seek(fd, 0, 2);
1117 7ce2007c 2006-02-12 devnull printunixfrom(fd);
1118 7ce2007c 2006-02-12 devnull targ = emalloc(3*sizeof targ[0]);
1119 7ce2007c 2006-02-12 devnull targ[0] = sfd;
1120 7ce2007c 2006-02-12 devnull targ[1] = pfd[0];
1121 7ce2007c 2006-02-12 devnull targ[2] = fd;
1122 7ce2007c 2006-02-12 devnull proccreate(teeproc, targ, STACK);
1123 7ce2007c 2006-02-12 devnull sfd = pfd[1];
1124 5cdb1798 2005-10-29 devnull }
1125 7ce2007c 2006-02-12 devnull
1126 7ce2007c 2006-02-12 devnull return sfd;
1127 5cdb1798 2005-10-29 devnull }
1128 5cdb1798 2005-10-29 devnull
1129 cbeb0b26 2006-04-01 devnull /* start up pgp process and return an fd to talk to it with. */
1130 cbeb0b26 2006-04-01 devnull /* its standard output will be the original fd, which goes to sendmail. */
1131 5cdb1798 2005-10-29 devnull int
1132 5cdb1798 2005-10-29 devnull pgpfilter(int *pid, int fd, int pgpflag)
1133 5cdb1798 2005-10-29 devnull {
1134 5cdb1798 2005-10-29 devnull char **av, **v;
1135 5cdb1798 2005-10-29 devnull int ac;
1136 5cdb1798 2005-10-29 devnull int pfd[2];
1137 5cdb1798 2005-10-29 devnull
1138 5cdb1798 2005-10-29 devnull v = av = emalloc(sizeof(char*)*8);
1139 5cdb1798 2005-10-29 devnull ac = 0;
1140 5cdb1798 2005-10-29 devnull v[ac++] = "pgp";
1141 b5f65921 2006-02-11 devnull v[ac++] = "-fat"; /* operate as a filter, generate text */
1142 5cdb1798 2005-10-29 devnull if(pgpflag & PGPsign)
1143 5cdb1798 2005-10-29 devnull v[ac++] = "-s";
1144 5cdb1798 2005-10-29 devnull if(pgpflag & PGPencrypt)
1145 5cdb1798 2005-10-29 devnull v[ac++] = "-e";
1146 5cdb1798 2005-10-29 devnull v[ac] = 0;
1147 5cdb1798 2005-10-29 devnull
1148 5cdb1798 2005-10-29 devnull if(pipe(pfd) < 0)
1149 5cdb1798 2005-10-29 devnull fatal("%r");
1150 5cdb1798 2005-10-29 devnull switch(*pid = fork()){
1151 5cdb1798 2005-10-29 devnull case -1:
1152 5cdb1798 2005-10-29 devnull fatal("%r");
1153 5cdb1798 2005-10-29 devnull break;
1154 5cdb1798 2005-10-29 devnull case 0:
1155 5cdb1798 2005-10-29 devnull close(pfd[1]);
1156 5cdb1798 2005-10-29 devnull dup(pfd[0], 0);
1157 5cdb1798 2005-10-29 devnull close(pfd[0]);
1158 5cdb1798 2005-10-29 devnull dup(fd, 1);
1159 5cdb1798 2005-10-29 devnull close(fd);
1160 b5f65921 2006-02-11 devnull /* add newline to avoid confusing pgp output with 822 headers */
1161 b5f65921 2006-02-11 devnull write(1, "\n", 1);
1162 5cdb1798 2005-10-29 devnull
1163 b5f65921 2006-02-11 devnull exec("pgp", av);
1164 5cdb1798 2005-10-29 devnull fatal("execing: %r");
1165 5cdb1798 2005-10-29 devnull break;
1166 5cdb1798 2005-10-29 devnull default:
1167 5cdb1798 2005-10-29 devnull close(pfd[0]);
1168 5cdb1798 2005-10-29 devnull break;
1169 5cdb1798 2005-10-29 devnull }
1170 5cdb1798 2005-10-29 devnull close(fd);
1171 5cdb1798 2005-10-29 devnull return pfd[1];
1172 5cdb1798 2005-10-29 devnull }
1173 5cdb1798 2005-10-29 devnull
1174 cbeb0b26 2006-04-01 devnull /* wait for sendmail and pgp to exit; exit here if either failed */
1175 5cdb1798 2005-10-29 devnull char*
1176 5cdb1798 2005-10-29 devnull waitforsubprocs(void)
1177 5cdb1798 2005-10-29 devnull {
1178 5cdb1798 2005-10-29 devnull Waitmsg *w;
1179 5cdb1798 2005-10-29 devnull char *err;
1180 5cdb1798 2005-10-29 devnull
1181 5cdb1798 2005-10-29 devnull err = nil;
1182 7ce2007c 2006-02-12 devnull if(pgppid >= 0 && (w=procwait(pgppid)) && w->msg[0])
1183 7ce2007c 2006-02-12 devnull err = w->msg;
1184 7ce2007c 2006-02-12 devnull if(pid >= 0 && (w=procwait(pid)) && w->msg[0])
1185 7ce2007c 2006-02-12 devnull err = w->msg;
1186 bae34df8 2014-05-15 0intro return err;
1187 5cdb1798 2005-10-29 devnull }
1188 5cdb1798 2005-10-29 devnull
1189 5cdb1798 2005-10-29 devnull int
1190 5cdb1798 2005-10-29 devnull cistrncmp(char *a, char *b, int n)
1191 5cdb1798 2005-10-29 devnull {
1192 5cdb1798 2005-10-29 devnull while(n-- > 0){
1193 5cdb1798 2005-10-29 devnull if(tolower(*a++) != tolower(*b++))
1194 5cdb1798 2005-10-29 devnull return -1;
1195 5cdb1798 2005-10-29 devnull }
1196 5cdb1798 2005-10-29 devnull return 0;
1197 5cdb1798 2005-10-29 devnull }
1198 5cdb1798 2005-10-29 devnull
1199 5cdb1798 2005-10-29 devnull int
1200 5cdb1798 2005-10-29 devnull cistrcmp(char *a, char *b)
1201 5cdb1798 2005-10-29 devnull {
1202 5cdb1798 2005-10-29 devnull for(;;){
1203 5cdb1798 2005-10-29 devnull if(tolower(*a) != tolower(*b++))
1204 5cdb1798 2005-10-29 devnull return -1;
1205 5cdb1798 2005-10-29 devnull if(*a++ == 0)
1206 5cdb1798 2005-10-29 devnull break;
1207 5cdb1798 2005-10-29 devnull }
1208 5cdb1798 2005-10-29 devnull return 0;
1209 5cdb1798 2005-10-29 devnull }
1210 5cdb1798 2005-10-29 devnull
1211 5cdb1798 2005-10-29 devnull static uchar t64d[256];
1212 5cdb1798 2005-10-29 devnull static char t64e[64];
1213 5cdb1798 2005-10-29 devnull
1214 5cdb1798 2005-10-29 devnull static void
1215 5cdb1798 2005-10-29 devnull init64(void)
1216 5cdb1798 2005-10-29 devnull {
1217 5cdb1798 2005-10-29 devnull int c, i;
1218 5cdb1798 2005-10-29 devnull
1219 5cdb1798 2005-10-29 devnull memset(t64d, 255, 256);
1220 5cdb1798 2005-10-29 devnull memset(t64e, '=', 64);
1221 5cdb1798 2005-10-29 devnull i = 0;
1222 5cdb1798 2005-10-29 devnull for(c = 'A'; c <= 'Z'; c++){
1223 5cdb1798 2005-10-29 devnull t64e[i] = c;
1224 5cdb1798 2005-10-29 devnull t64d[c] = i++;
1225 5cdb1798 2005-10-29 devnull }
1226 5cdb1798 2005-10-29 devnull for(c = 'a'; c <= 'z'; c++){
1227 5cdb1798 2005-10-29 devnull t64e[i] = c;
1228 5cdb1798 2005-10-29 devnull t64d[c] = i++;
1229 5cdb1798 2005-10-29 devnull }
1230 5cdb1798 2005-10-29 devnull for(c = '0'; c <= '9'; c++){
1231 5cdb1798 2005-10-29 devnull t64e[i] = c;
1232 5cdb1798 2005-10-29 devnull t64d[c] = i++;
1233 5cdb1798 2005-10-29 devnull }
1234 5cdb1798 2005-10-29 devnull t64e[i] = '+';
1235 5cdb1798 2005-10-29 devnull t64d['+'] = i++;
1236 5cdb1798 2005-10-29 devnull t64e[i] = '/';
1237 5cdb1798 2005-10-29 devnull t64d['/'] = i;
1238 5cdb1798 2005-10-29 devnull }
1239 5cdb1798 2005-10-29 devnull
1240 5cdb1798 2005-10-29 devnull int
1241 5cdb1798 2005-10-29 devnull enc64(char *out, int lim, uchar *in, int n)
1242 5cdb1798 2005-10-29 devnull {
1243 5cdb1798 2005-10-29 devnull int i;
1244 5cdb1798 2005-10-29 devnull ulong b24;
1245 5cdb1798 2005-10-29 devnull char *start = out;
1246 5cdb1798 2005-10-29 devnull char *e = out + lim;
1247 5cdb1798 2005-10-29 devnull
1248 5cdb1798 2005-10-29 devnull if(t64e[0] == 0)
1249 5cdb1798 2005-10-29 devnull init64();
1250 5cdb1798 2005-10-29 devnull for(i = 0; i < n/3; i++){
1251 5cdb1798 2005-10-29 devnull b24 = (*in++)<<16;
1252 5cdb1798 2005-10-29 devnull b24 |= (*in++)<<8;
1253 5cdb1798 2005-10-29 devnull b24 |= *in++;
1254 5cdb1798 2005-10-29 devnull if(out + 5 >= e)
1255 5cdb1798 2005-10-29 devnull goto exhausted;
1256 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>18)];
1257 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>12)&0x3f];
1258 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>6)&0x3f];
1259 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24)&0x3f];
1260 5cdb1798 2005-10-29 devnull if((i%18) == 17)
1261 5cdb1798 2005-10-29 devnull *out++ = '\n';
1262 5cdb1798 2005-10-29 devnull }
1263 5cdb1798 2005-10-29 devnull
1264 5cdb1798 2005-10-29 devnull switch(n%3){
1265 5cdb1798 2005-10-29 devnull case 2:
1266 5cdb1798 2005-10-29 devnull b24 = (*in++)<<16;
1267 5cdb1798 2005-10-29 devnull b24 |= (*in)<<8;
1268 5cdb1798 2005-10-29 devnull if(out + 4 >= e)
1269 5cdb1798 2005-10-29 devnull goto exhausted;
1270 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>18)];
1271 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>12)&0x3f];
1272 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>6)&0x3f];
1273 5cdb1798 2005-10-29 devnull break;
1274 5cdb1798 2005-10-29 devnull case 1:
1275 5cdb1798 2005-10-29 devnull b24 = (*in)<<16;
1276 5cdb1798 2005-10-29 devnull if(out + 4 >= e)
1277 5cdb1798 2005-10-29 devnull goto exhausted;
1278 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>18)];
1279 5cdb1798 2005-10-29 devnull *out++ = t64e[(b24>>12)&0x3f];
1280 5cdb1798 2005-10-29 devnull *out++ = '=';
1281 5cdb1798 2005-10-29 devnull break;
1282 5cdb1798 2005-10-29 devnull case 0:
1283 5cdb1798 2005-10-29 devnull if((i%18) != 0)
1284 5cdb1798 2005-10-29 devnull *out++ = '\n';
1285 5cdb1798 2005-10-29 devnull *out = 0;
1286 5cdb1798 2005-10-29 devnull return out - start;
1287 5cdb1798 2005-10-29 devnull }
1288 5cdb1798 2005-10-29 devnull exhausted:
1289 5cdb1798 2005-10-29 devnull *out++ = '=';
1290 5cdb1798 2005-10-29 devnull *out++ = '\n';
1291 5cdb1798 2005-10-29 devnull *out = 0;
1292 5cdb1798 2005-10-29 devnull return out - start;
1293 5cdb1798 2005-10-29 devnull }
1294 5cdb1798 2005-10-29 devnull
1295 5cdb1798 2005-10-29 devnull void
1296 5cdb1798 2005-10-29 devnull freealias(Alias *a)
1297 5cdb1798 2005-10-29 devnull {
1298 5cdb1798 2005-10-29 devnull freeaddrs(a->addr);
1299 5cdb1798 2005-10-29 devnull free(a);
1300 5cdb1798 2005-10-29 devnull }
1301 5cdb1798 2005-10-29 devnull
1302 5cdb1798 2005-10-29 devnull void
1303 5cdb1798 2005-10-29 devnull freealiases(Alias *a)
1304 5cdb1798 2005-10-29 devnull {
1305 5cdb1798 2005-10-29 devnull Alias *next;
1306 5cdb1798 2005-10-29 devnull
1307 5cdb1798 2005-10-29 devnull while(a != nil){
1308 5cdb1798 2005-10-29 devnull next = a->next;
1309 5cdb1798 2005-10-29 devnull freealias(a);
1310 5cdb1798 2005-10-29 devnull a = next;
1311 5cdb1798 2005-10-29 devnull }
1312 5cdb1798 2005-10-29 devnull }
1313 5cdb1798 2005-10-29 devnull
1314 cbeb0b26 2006-04-01 devnull /* */
1315 cbeb0b26 2006-04-01 devnull /* read alias file */
1316 cbeb0b26 2006-04-01 devnull /* */
1317 5cdb1798 2005-10-29 devnull Alias*
1318 5cdb1798 2005-10-29 devnull readaliases(void)
1319 5cdb1798 2005-10-29 devnull {
1320 5cdb1798 2005-10-29 devnull Alias *a, **l, *first;
1321 5cdb1798 2005-10-29 devnull Addr *addr, **al;
1322 5cdb1798 2005-10-29 devnull String *file, *line, *token;
1323 5cdb1798 2005-10-29 devnull Sinstack *sp;
1324 5cdb1798 2005-10-29 devnull
1325 5cdb1798 2005-10-29 devnull first = nil;
1326 5cdb1798 2005-10-29 devnull file = s_new();
1327 5cdb1798 2005-10-29 devnull line = s_new();
1328 5cdb1798 2005-10-29 devnull token = s_new();
1329 5cdb1798 2005-10-29 devnull
1330 cbeb0b26 2006-04-01 devnull /* open and get length */
1331 5cdb1798 2005-10-29 devnull mboxpath("names", login, file, 0);
1332 5cdb1798 2005-10-29 devnull sp = s_allocinstack(s_to_c(file));
1333 5cdb1798 2005-10-29 devnull if(sp == nil)
1334 5cdb1798 2005-10-29 devnull goto out;
1335 5cdb1798 2005-10-29 devnull
1336 5cdb1798 2005-10-29 devnull l = &first;
1337 5cdb1798 2005-10-29 devnull
1338 cbeb0b26 2006-04-01 devnull /* read a line at a time. */
1339 5cdb1798 2005-10-29 devnull while(s_rdinstack(sp, s_restart(line))!=nil) {
1340 5cdb1798 2005-10-29 devnull s_restart(line);
1341 5cdb1798 2005-10-29 devnull a = emalloc(sizeof(Alias));
1342 5cdb1798 2005-10-29 devnull al = &a->addr;
1343 5cdb1798 2005-10-29 devnull for(;;){
1344 5cdb1798 2005-10-29 devnull if(s_parse(line, s_restart(token))==0)
1345 5cdb1798 2005-10-29 devnull break;
1346 5cdb1798 2005-10-29 devnull addr = emalloc(sizeof(Addr));
1347 5cdb1798 2005-10-29 devnull addr->v = strdup(s_to_c(token));
1348 5cdb1798 2005-10-29 devnull addr->next = 0;
1349 5cdb1798 2005-10-29 devnull *al = addr;
1350 5cdb1798 2005-10-29 devnull al = &addr->next;
1351 5cdb1798 2005-10-29 devnull }
1352 5cdb1798 2005-10-29 devnull if(a->addr == nil || a->addr->next == nil){
1353 5cdb1798 2005-10-29 devnull freealias(a);
1354 5cdb1798 2005-10-29 devnull continue;
1355 5cdb1798 2005-10-29 devnull }
1356 5cdb1798 2005-10-29 devnull a->next = nil;
1357 5cdb1798 2005-10-29 devnull *l = a;
1358 5cdb1798 2005-10-29 devnull l = &a->next;
1359 5cdb1798 2005-10-29 devnull }
1360 5cdb1798 2005-10-29 devnull s_freeinstack(sp);
1361 5cdb1798 2005-10-29 devnull
1362 5cdb1798 2005-10-29 devnull out:
1363 5cdb1798 2005-10-29 devnull s_free(file);
1364 5cdb1798 2005-10-29 devnull s_free(line);
1365 5cdb1798 2005-10-29 devnull s_free(token);
1366 5cdb1798 2005-10-29 devnull return first;
1367 5cdb1798 2005-10-29 devnull }
1368 5cdb1798 2005-10-29 devnull
1369 5cdb1798 2005-10-29 devnull Addr*
1370 5cdb1798 2005-10-29 devnull newaddr(char *name)
1371 5cdb1798 2005-10-29 devnull {
1372 5cdb1798 2005-10-29 devnull Addr *a;
1373 5cdb1798 2005-10-29 devnull
1374 5cdb1798 2005-10-29 devnull a = emalloc(sizeof(*a));
1375 5cdb1798 2005-10-29 devnull a->next = nil;
1376 5cdb1798 2005-10-29 devnull a->v = estrdup(name);
1377 5cdb1798 2005-10-29 devnull if(a->v == nil)
1378 5cdb1798 2005-10-29 devnull sysfatal("%r");
1379 5cdb1798 2005-10-29 devnull return a;
1380 5cdb1798 2005-10-29 devnull }
1381 5cdb1798 2005-10-29 devnull
1382 cbeb0b26 2006-04-01 devnull /* */
1383 cbeb0b26 2006-04-01 devnull /* expand personal aliases since the names are meaningless in */
1384 cbeb0b26 2006-04-01 devnull /* other contexts */
1385 cbeb0b26 2006-04-01 devnull /* */
1386 5cdb1798 2005-10-29 devnull Addr*
1387 5cdb1798 2005-10-29 devnull _expand(Addr *old, int *changedp)
1388 5cdb1798 2005-10-29 devnull {
1389 5cdb1798 2005-10-29 devnull Alias *al;
1390 5cdb1798 2005-10-29 devnull Addr *first, *next, **l, *a;
1391 5cdb1798 2005-10-29 devnull
1392 5cdb1798 2005-10-29 devnull *changedp = 0;
1393 5cdb1798 2005-10-29 devnull first = nil;
1394 5cdb1798 2005-10-29 devnull l = &first;
1395 5cdb1798 2005-10-29 devnull for(;old != nil; old = next){
1396 5cdb1798 2005-10-29 devnull next = old->next;
1397 5cdb1798 2005-10-29 devnull for(al = aliases; al != nil; al = al->next){
1398 5cdb1798 2005-10-29 devnull if(strcmp(al->addr->v, old->v) == 0){
1399 5cdb1798 2005-10-29 devnull for(a = al->addr->next; a != nil; a = a->next){
1400 5cdb1798 2005-10-29 devnull *l = newaddr(a->v);
1401 5cdb1798 2005-10-29 devnull if(*l == nil)
1402 5cdb1798 2005-10-29 devnull sysfatal("%r");
1403 5cdb1798 2005-10-29 devnull l = &(*l)->next;
1404 5cdb1798 2005-10-29 devnull *changedp = 1;
1405 5cdb1798 2005-10-29 devnull }
1406 5cdb1798 2005-10-29 devnull break;
1407 5cdb1798 2005-10-29 devnull }
1408 5cdb1798 2005-10-29 devnull }
1409 5cdb1798 2005-10-29 devnull if(al != nil){
1410 5cdb1798 2005-10-29 devnull freeaddr(old);
1411 5cdb1798 2005-10-29 devnull continue;
1412 5cdb1798 2005-10-29 devnull }
1413 5cdb1798 2005-10-29 devnull *l = old;
1414 5cdb1798 2005-10-29 devnull old->next = nil;
1415 5cdb1798 2005-10-29 devnull l = &(*l)->next;
1416 5cdb1798 2005-10-29 devnull }
1417 5cdb1798 2005-10-29 devnull return first;
1418 5cdb1798 2005-10-29 devnull }
1419 5cdb1798 2005-10-29 devnull
1420 5cdb1798 2005-10-29 devnull Addr*
1421 5cdb1798 2005-10-29 devnull rexpand(Addr *old)
1422 5cdb1798 2005-10-29 devnull {
1423 5cdb1798 2005-10-29 devnull int i, changed;
1424 5cdb1798 2005-10-29 devnull
1425 5cdb1798 2005-10-29 devnull changed = 0;
1426 5cdb1798 2005-10-29 devnull for(i=0; i<32; i++){
1427 5cdb1798 2005-10-29 devnull old = _expand(old, &changed);
1428 5cdb1798 2005-10-29 devnull if(changed == 0)
1429 5cdb1798 2005-10-29 devnull break;
1430 5cdb1798 2005-10-29 devnull }
1431 5cdb1798 2005-10-29 devnull return old;
1432 5cdb1798 2005-10-29 devnull }
1433 5cdb1798 2005-10-29 devnull
1434 5cdb1798 2005-10-29 devnull Addr*
1435 5cdb1798 2005-10-29 devnull unique(Addr *first)
1436 5cdb1798 2005-10-29 devnull {
1437 5cdb1798 2005-10-29 devnull Addr *a, **l, *x;
1438 5cdb1798 2005-10-29 devnull
1439 5cdb1798 2005-10-29 devnull for(a = first; a != nil; a = a->next){
1440 5cdb1798 2005-10-29 devnull for(l = &a->next; *l != nil;){
1441 5cdb1798 2005-10-29 devnull if(strcmp(a->v, (*l)->v) == 0){
1442 5cdb1798 2005-10-29 devnull x = *l;
1443 5cdb1798 2005-10-29 devnull *l = x->next;
1444 5cdb1798 2005-10-29 devnull freeaddr(x);
1445 5cdb1798 2005-10-29 devnull } else
1446 5cdb1798 2005-10-29 devnull l = &(*l)->next;
1447 5cdb1798 2005-10-29 devnull }
1448 5cdb1798 2005-10-29 devnull }
1449 5cdb1798 2005-10-29 devnull return first;
1450 5cdb1798 2005-10-29 devnull }
1451 5cdb1798 2005-10-29 devnull
1452 5cdb1798 2005-10-29 devnull Addr*
1453 5cdb1798 2005-10-29 devnull expand(int ac, char **av)
1454 5cdb1798 2005-10-29 devnull {
1455 5cdb1798 2005-10-29 devnull Addr *first, **l;
1456 5cdb1798 2005-10-29 devnull int i;
1457 5cdb1798 2005-10-29 devnull
1458 5cdb1798 2005-10-29 devnull first = nil;
1459 5cdb1798 2005-10-29 devnull
1460 cbeb0b26 2006-04-01 devnull /* make a list of the starting addresses */
1461 5cdb1798 2005-10-29 devnull l = &first;
1462 5cdb1798 2005-10-29 devnull for(i = 0; i < ac; i++){
1463 5cdb1798 2005-10-29 devnull *l = newaddr(av[i]);
1464 5cdb1798 2005-10-29 devnull if(*l == nil)
1465 5cdb1798 2005-10-29 devnull sysfatal("%r");
1466 5cdb1798 2005-10-29 devnull l = &(*l)->next;
1467 5cdb1798 2005-10-29 devnull }
1468 5cdb1798 2005-10-29 devnull
1469 cbeb0b26 2006-04-01 devnull /* recurse till we don't change any more */
1470 5cdb1798 2005-10-29 devnull return unique(rexpand(first));
1471 5cdb1798 2005-10-29 devnull }
1472 5cdb1798 2005-10-29 devnull
1473 5cdb1798 2005-10-29 devnull Addr*
1474 5cdb1798 2005-10-29 devnull concataddr(Addr *a, Addr *b)
1475 5cdb1798 2005-10-29 devnull {
1476 5cdb1798 2005-10-29 devnull Addr *oa;
1477 5cdb1798 2005-10-29 devnull
1478 5cdb1798 2005-10-29 devnull if(a == nil)
1479 5cdb1798 2005-10-29 devnull return b;
1480 5cdb1798 2005-10-29 devnull
1481 5cdb1798 2005-10-29 devnull oa = a;
1482 5cdb1798 2005-10-29 devnull for(; a->next; a=a->next)
1483 5cdb1798 2005-10-29 devnull ;
1484 5cdb1798 2005-10-29 devnull a->next = b;
1485 5cdb1798 2005-10-29 devnull return oa;
1486 5cdb1798 2005-10-29 devnull }
1487 5cdb1798 2005-10-29 devnull
1488 5cdb1798 2005-10-29 devnull void
1489 5cdb1798 2005-10-29 devnull freeaddr(Addr *ap)
1490 5cdb1798 2005-10-29 devnull {
1491 5cdb1798 2005-10-29 devnull free(ap->v);
1492 5cdb1798 2005-10-29 devnull free(ap);
1493 5cdb1798 2005-10-29 devnull }
1494 5cdb1798 2005-10-29 devnull
1495 5cdb1798 2005-10-29 devnull void
1496 5cdb1798 2005-10-29 devnull freeaddrs(Addr *ap)
1497 5cdb1798 2005-10-29 devnull {
1498 5cdb1798 2005-10-29 devnull Addr *next;
1499 5cdb1798 2005-10-29 devnull
1500 5cdb1798 2005-10-29 devnull for(; ap; ap=next) {
1501 5cdb1798 2005-10-29 devnull next = ap->next;
1502 5cdb1798 2005-10-29 devnull freeaddr(ap);
1503 5cdb1798 2005-10-29 devnull }
1504 5cdb1798 2005-10-29 devnull }
1505 5cdb1798 2005-10-29 devnull
1506 5cdb1798 2005-10-29 devnull String*
1507 5cdb1798 2005-10-29 devnull s_copyn(char *s, int n)
1508 5cdb1798 2005-10-29 devnull {
1509 5cdb1798 2005-10-29 devnull return s_nappend(s_reset(nil), s, n);
1510 5cdb1798 2005-10-29 devnull }
1511 5cdb1798 2005-10-29 devnull
1512 cbeb0b26 2006-04-01 devnull /* fetch the next token from an RFC822 address string */
1513 cbeb0b26 2006-04-01 devnull /* we assume the header is RFC822-conformant in that */
1514 cbeb0b26 2006-04-01 devnull /* we recognize escaping anywhere even though it is only */
1515 cbeb0b26 2006-04-01 devnull /* supposed to be in quoted-strings, domain-literals, and comments. */
1516 cbeb0b26 2006-04-01 devnull /* */
1517 cbeb0b26 2006-04-01 devnull /* i'd use yylex or yyparse here, but we need to preserve */
1518 cbeb0b26 2006-04-01 devnull /* things like comments, which i think it tosses away. */
1519 cbeb0b26 2006-04-01 devnull /* */
1520 cbeb0b26 2006-04-01 devnull /* we're not strictly RFC822 compliant. we misparse such nonsense as */
1521 cbeb0b26 2006-04-01 devnull /* */
1522 cbeb0b26 2006-04-01 devnull /* To: gre @ (Grace) plan9 . (Emlin) bell-labs.com */
1523 cbeb0b26 2006-04-01 devnull /* */
1524 cbeb0b26 2006-04-01 devnull /* make sure there's no whitespace in your addresses and */
1525 cbeb0b26 2006-04-01 devnull /* you'll be fine. */
1526 cbeb0b26 2006-04-01 devnull /* */
1527 5cdb1798 2005-10-29 devnull enum {
1528 5cdb1798 2005-10-29 devnull Twhite,
1529 5cdb1798 2005-10-29 devnull Tcomment,
1530 5cdb1798 2005-10-29 devnull Twords,
1531 5cdb1798 2005-10-29 devnull Tcomma,
1532 5cdb1798 2005-10-29 devnull Tleftangle,
1533 5cdb1798 2005-10-29 devnull Trightangle,
1534 5cdb1798 2005-10-29 devnull Terror,
1535 cbeb0b26 2006-04-01 devnull Tend
1536 5cdb1798 2005-10-29 devnull };
1537 cbeb0b26 2006-04-01 devnull /*char *ty82[] = {"white", "comment", "words", "comma", "<", ">", "err", "end"}; */
1538 5cdb1798 2005-10-29 devnull #define ISWHITE(p) ((p)==' ' || (p)=='\t' || (p)=='\n' || (p)=='\r')
1539 5cdb1798 2005-10-29 devnull int
1540 5cdb1798 2005-10-29 devnull get822token(String **tok, char *p, char **pp)
1541 5cdb1798 2005-10-29 devnull {
1542 5cdb1798 2005-10-29 devnull char *op;
1543 5cdb1798 2005-10-29 devnull int type;
1544 5cdb1798 2005-10-29 devnull int quoting;
1545 5cdb1798 2005-10-29 devnull
1546 5cdb1798 2005-10-29 devnull op = p;
1547 5cdb1798 2005-10-29 devnull switch(*p){
1548 5cdb1798 2005-10-29 devnull case '\0':
1549 5cdb1798 2005-10-29 devnull *tok = nil;
1550 5cdb1798 2005-10-29 devnull *pp = nil;
1551 5cdb1798 2005-10-29 devnull return Tend;
1552 5cdb1798 2005-10-29 devnull
1553 cbeb0b26 2006-04-01 devnull case ' ': /* get whitespace */
1554 5cdb1798 2005-10-29 devnull case '\t':
1555 5cdb1798 2005-10-29 devnull case '\n':
1556 5cdb1798 2005-10-29 devnull case '\r':
1557 5cdb1798 2005-10-29 devnull type = Twhite;
1558 5cdb1798 2005-10-29 devnull while(ISWHITE(*p))
1559 5cdb1798 2005-10-29 devnull p++;
1560 5cdb1798 2005-10-29 devnull break;
1561 5cdb1798 2005-10-29 devnull
1562 cbeb0b26 2006-04-01 devnull case '(': /* get comment */
1563 5cdb1798 2005-10-29 devnull type = Tcomment;
1564 5cdb1798 2005-10-29 devnull for(p++; *p && *p != ')'; p++)
1565 5cdb1798 2005-10-29 devnull if(*p == '\\') {
1566 5cdb1798 2005-10-29 devnull if(*(p+1) == '\0') {
1567 5cdb1798 2005-10-29 devnull *tok = nil;
1568 5cdb1798 2005-10-29 devnull return Terror;
1569 5cdb1798 2005-10-29 devnull }
1570 5cdb1798 2005-10-29 devnull p++;
1571 5cdb1798 2005-10-29 devnull }
1572 5cdb1798 2005-10-29 devnull
1573 5cdb1798 2005-10-29 devnull if(*p != ')') {
1574 5cdb1798 2005-10-29 devnull *tok = nil;
1575 5cdb1798 2005-10-29 devnull return Terror;
1576 5cdb1798 2005-10-29 devnull }
1577 5cdb1798 2005-10-29 devnull p++;
1578 5cdb1798 2005-10-29 devnull break;
1579 5cdb1798 2005-10-29 devnull case ',':
1580 5cdb1798 2005-10-29 devnull type = Tcomma;
1581 5cdb1798 2005-10-29 devnull p++;
1582 5cdb1798 2005-10-29 devnull break;
1583 5cdb1798 2005-10-29 devnull case '<':
1584 5cdb1798 2005-10-29 devnull type = Tleftangle;
1585 5cdb1798 2005-10-29 devnull p++;
1586 5cdb1798 2005-10-29 devnull break;
1587 5cdb1798 2005-10-29 devnull case '>':
1588 5cdb1798 2005-10-29 devnull type = Trightangle;
1589 5cdb1798 2005-10-29 devnull p++;
1590 5cdb1798 2005-10-29 devnull break;
1591 cbeb0b26 2006-04-01 devnull default: /* bunch of letters, perhaps quoted strings tossed in */
1592 5cdb1798 2005-10-29 devnull type = Twords;
1593 5cdb1798 2005-10-29 devnull quoting = 0;
1594 5cdb1798 2005-10-29 devnull for(; *p && (quoting || (!ISWHITE(*p) && *p != '>' && *p != '<' && *p != ',')); p++) {
1595 5cdb1798 2005-10-29 devnull if(*p == '"')
1596 5cdb1798 2005-10-29 devnull quoting = !quoting;
1597 5cdb1798 2005-10-29 devnull if(*p == '\\') {
1598 5cdb1798 2005-10-29 devnull if(*(p+1) == '\0') {
1599 5cdb1798 2005-10-29 devnull *tok = nil;
1600 5cdb1798 2005-10-29 devnull return Terror;
1601 5cdb1798 2005-10-29 devnull }
1602 5cdb1798 2005-10-29 devnull p++;
1603 5cdb1798 2005-10-29 devnull }
1604 5cdb1798 2005-10-29 devnull }
1605 5cdb1798 2005-10-29 devnull break;
1606 5cdb1798 2005-10-29 devnull }
1607 5cdb1798 2005-10-29 devnull
1608 5cdb1798 2005-10-29 devnull if(pp)
1609 5cdb1798 2005-10-29 devnull *pp = p;
1610 5cdb1798 2005-10-29 devnull *tok = s_copyn(op, p-op);
1611 5cdb1798 2005-10-29 devnull return type;
1612 5cdb1798 2005-10-29 devnull }
1613 5cdb1798 2005-10-29 devnull
1614 cbeb0b26 2006-04-01 devnull /* expand local aliases in an RFC822 mail line */
1615 cbeb0b26 2006-04-01 devnull /* add list of expanded addresses to to. */
1616 5cdb1798 2005-10-29 devnull Addr*
1617 5cdb1798 2005-10-29 devnull expandline(String **s, Addr *to)
1618 5cdb1798 2005-10-29 devnull {
1619 5cdb1798 2005-10-29 devnull Addr *na, *nto, *ap;
1620 5cdb1798 2005-10-29 devnull char *p;
1621 5cdb1798 2005-10-29 devnull int tok, inangle, hadangle, nword;
1622 5cdb1798 2005-10-29 devnull String *os, *ns, *stok, *lastword, *sinceword;
1623 5cdb1798 2005-10-29 devnull
1624 5cdb1798 2005-10-29 devnull os = s_copy(s_to_c(*s));
1625 5cdb1798 2005-10-29 devnull p = strchr(s_to_c(*s), ':');
1626 5cdb1798 2005-10-29 devnull assert(p != nil);
1627 5cdb1798 2005-10-29 devnull p++;
1628 5cdb1798 2005-10-29 devnull
1629 5cdb1798 2005-10-29 devnull ns = s_copyn(s_to_c(*s), p-s_to_c(*s));
1630 5cdb1798 2005-10-29 devnull stok = nil;
1631 5cdb1798 2005-10-29 devnull nto = nil;
1632 cbeb0b26 2006-04-01 devnull /* */
1633 cbeb0b26 2006-04-01 devnull /* the only valid mailbox namings are word */
1634 cbeb0b26 2006-04-01 devnull /* and word* < addr > */
1635 cbeb0b26 2006-04-01 devnull /* without comments this would be simple. */
1636 cbeb0b26 2006-04-01 devnull /* we keep the following: */
1637 cbeb0b26 2006-04-01 devnull /* lastword - current guess at the address */
1638 cbeb0b26 2006-04-01 devnull /* sinceword - whitespace and comment seen since lastword */
1639 cbeb0b26 2006-04-01 devnull /* */
1640 5cdb1798 2005-10-29 devnull lastword = s_new();
1641 5cdb1798 2005-10-29 devnull sinceword = s_new();
1642 5cdb1798 2005-10-29 devnull inangle = 0;
1643 5cdb1798 2005-10-29 devnull nword = 0;
1644 5cdb1798 2005-10-29 devnull hadangle = 0;
1645 5cdb1798 2005-10-29 devnull for(;;) {
1646 5cdb1798 2005-10-29 devnull stok = nil;
1647 5cdb1798 2005-10-29 devnull switch(tok = get822token(&stok, p, &p)){
1648 5cdb1798 2005-10-29 devnull default:
1649 5cdb1798 2005-10-29 devnull abort();
1650 5cdb1798 2005-10-29 devnull case Tcomma:
1651 5cdb1798 2005-10-29 devnull case Tend:
1652 5cdb1798 2005-10-29 devnull if(inangle)
1653 5cdb1798 2005-10-29 devnull goto Error;
1654 5cdb1798 2005-10-29 devnull if(nword != 1)
1655 5cdb1798 2005-10-29 devnull goto Error;
1656 5cdb1798 2005-10-29 devnull na = rexpand(newaddr(s_to_c(lastword)));
1657 5cdb1798 2005-10-29 devnull s_append(ns, na->v);
1658 5cdb1798 2005-10-29 devnull s_append(ns, s_to_c(sinceword));
1659 5cdb1798 2005-10-29 devnull for(ap=na->next; ap; ap=ap->next) {
1660 5cdb1798 2005-10-29 devnull s_append(ns, ", ");
1661 5cdb1798 2005-10-29 devnull s_append(ns, ap->v);
1662 5cdb1798 2005-10-29 devnull }
1663 5cdb1798 2005-10-29 devnull nto = concataddr(na, nto);
1664 5cdb1798 2005-10-29 devnull if(tok == Tcomma){
1665 5cdb1798 2005-10-29 devnull s_append(ns, ",");
1666 5cdb1798 2005-10-29 devnull s_free(stok);
1667 5cdb1798 2005-10-29 devnull }
1668 5cdb1798 2005-10-29 devnull if(tok == Tend)
1669 5cdb1798 2005-10-29 devnull goto Break2;
1670 5cdb1798 2005-10-29 devnull inangle = 0;
1671 5cdb1798 2005-10-29 devnull nword = 0;
1672 5cdb1798 2005-10-29 devnull hadangle = 0;
1673 5cdb1798 2005-10-29 devnull s_reset(sinceword);
1674 5cdb1798 2005-10-29 devnull s_reset(lastword);
1675 5cdb1798 2005-10-29 devnull break;
1676 5cdb1798 2005-10-29 devnull case Twhite:
1677 5cdb1798 2005-10-29 devnull case Tcomment:
1678 5cdb1798 2005-10-29 devnull s_append(sinceword, s_to_c(stok));
1679 5cdb1798 2005-10-29 devnull s_free(stok);
1680 5cdb1798 2005-10-29 devnull break;
1681 5cdb1798 2005-10-29 devnull case Trightangle:
1682 5cdb1798 2005-10-29 devnull if(!inangle)
1683 5cdb1798 2005-10-29 devnull goto Error;
1684 5cdb1798 2005-10-29 devnull inangle = 0;
1685 5cdb1798 2005-10-29 devnull hadangle = 1;
1686 5cdb1798 2005-10-29 devnull s_append(sinceword, s_to_c(stok));
1687 5cdb1798 2005-10-29 devnull s_free(stok);
1688 5cdb1798 2005-10-29 devnull break;
1689 5cdb1798 2005-10-29 devnull case Twords:
1690 5cdb1798 2005-10-29 devnull case Tleftangle:
1691 5cdb1798 2005-10-29 devnull if(hadangle)
1692 5cdb1798 2005-10-29 devnull goto Error;
1693 5cdb1798 2005-10-29 devnull if(tok != Tleftangle && inangle && s_len(lastword))
1694 5cdb1798 2005-10-29 devnull goto Error;
1695 5cdb1798 2005-10-29 devnull if(tok == Tleftangle) {
1696 5cdb1798 2005-10-29 devnull inangle = 1;
1697 5cdb1798 2005-10-29 devnull nword = 1;
1698 5cdb1798 2005-10-29 devnull }
1699 5cdb1798 2005-10-29 devnull s_append(ns, s_to_c(lastword));
1700 5cdb1798 2005-10-29 devnull s_append(ns, s_to_c(sinceword));
1701 5cdb1798 2005-10-29 devnull s_reset(sinceword);
1702 5cdb1798 2005-10-29 devnull if(tok == Tleftangle) {
1703 5cdb1798 2005-10-29 devnull s_append(ns, "<");
1704 5cdb1798 2005-10-29 devnull s_reset(lastword);
1705 5cdb1798 2005-10-29 devnull } else {
1706 5cdb1798 2005-10-29 devnull s_free(lastword);
1707 5cdb1798 2005-10-29 devnull lastword = stok;
1708 5cdb1798 2005-10-29 devnull }
1709 5cdb1798 2005-10-29 devnull if(!inangle)
1710 5cdb1798 2005-10-29 devnull nword++;
1711 5cdb1798 2005-10-29 devnull break;
1712 cbeb0b26 2006-04-01 devnull case Terror: /* give up, use old string, addrs */
1713 5cdb1798 2005-10-29 devnull Error:
1714 5cdb1798 2005-10-29 devnull ns = os;
1715 5cdb1798 2005-10-29 devnull os = nil;
1716 5cdb1798 2005-10-29 devnull freeaddrs(nto);
1717 5cdb1798 2005-10-29 devnull nto = nil;
1718 5cdb1798 2005-10-29 devnull werrstr("rfc822 syntax error");
1719 5cdb1798 2005-10-29 devnull rfc822syntaxerror = 1;
1720 5cdb1798 2005-10-29 devnull goto Break2;
1721 5cdb1798 2005-10-29 devnull }
1722 5cdb1798 2005-10-29 devnull }
1723 5cdb1798 2005-10-29 devnull Break2:
1724 5cdb1798 2005-10-29 devnull s_free(*s);
1725 5cdb1798 2005-10-29 devnull s_free(os);
1726 5cdb1798 2005-10-29 devnull *s = ns;
1727 5cdb1798 2005-10-29 devnull nto = concataddr(nto, to);
1728 5cdb1798 2005-10-29 devnull return nto;
1729 5cdb1798 2005-10-29 devnull }
1730 5cdb1798 2005-10-29 devnull
1731 5cdb1798 2005-10-29 devnull void
1732 5cdb1798 2005-10-29 devnull Bdrain(Biobuf *b)
1733 5cdb1798 2005-10-29 devnull {
1734 5cdb1798 2005-10-29 devnull char buf[8192];
1735 5cdb1798 2005-10-29 devnull
1736 5cdb1798 2005-10-29 devnull while(Bread(b, buf, sizeof buf) > 0)
1737 5cdb1798 2005-10-29 devnull ;
1738 5cdb1798 2005-10-29 devnull }
1739 5cdb1798 2005-10-29 devnull
1740 5cdb1798 2005-10-29 devnull void
1741 5cdb1798 2005-10-29 devnull readmimetypes(void)
1742 5cdb1798 2005-10-29 devnull {
1743 5cdb1798 2005-10-29 devnull Biobuf *b;
1744 5cdb1798 2005-10-29 devnull char *p;
1745 5cdb1798 2005-10-29 devnull char *f[6];
1746 5cdb1798 2005-10-29 devnull char type[256];
1747 5cdb1798 2005-10-29 devnull static int alloced, inuse;
1748 5cdb1798 2005-10-29 devnull
1749 5cdb1798 2005-10-29 devnull if(mimetypes == 0){
1750 5cdb1798 2005-10-29 devnull alloced = 256;
1751 5cdb1798 2005-10-29 devnull mimetypes = emalloc(alloced*sizeof(Ctype));
1752 5cdb1798 2005-10-29 devnull mimetypes[0].ext = "";
1753 5cdb1798 2005-10-29 devnull }
1754 5cdb1798 2005-10-29 devnull
1755 b5f65921 2006-02-11 devnull b = Bopen(unsharp("#9/lib/mimetype"), OREAD);
1756 5cdb1798 2005-10-29 devnull if(b == nil)
1757 5cdb1798 2005-10-29 devnull return;
1758 5cdb1798 2005-10-29 devnull for(;;){
1759 5cdb1798 2005-10-29 devnull p = Brdline(b, '\n');
1760 5cdb1798 2005-10-29 devnull if(p == nil)
1761 5cdb1798 2005-10-29 devnull break;
1762 5cdb1798 2005-10-29 devnull p[Blinelen(b)-1] = 0;
1763 5cdb1798 2005-10-29 devnull if(tokenize(p, f, 6) < 4)
1764 5cdb1798 2005-10-29 devnull continue;
1765 5cdb1798 2005-10-29 devnull if(strcmp(f[0], "-") == 0 || strcmp(f[1], "-") == 0 || strcmp(f[2], "-") == 0)
1766 5cdb1798 2005-10-29 devnull continue;
1767 5cdb1798 2005-10-29 devnull if(inuse + 1 >= alloced){
1768 5cdb1798 2005-10-29 devnull alloced += 256;
1769 5cdb1798 2005-10-29 devnull mimetypes = erealloc(mimetypes, alloced*sizeof(Ctype));
1770 5cdb1798 2005-10-29 devnull }
1771 5cdb1798 2005-10-29 devnull snprint(type, sizeof(type), "%s/%s", f[1], f[2]);
1772 5cdb1798 2005-10-29 devnull mimetypes[inuse].type = estrdup(type);
1773 5cdb1798 2005-10-29 devnull mimetypes[inuse].ext = estrdup(f[0]+1);
1774 5cdb1798 2005-10-29 devnull mimetypes[inuse].display = !strcmp(type, "text/plain");
1775 5cdb1798 2005-10-29 devnull inuse++;
1776 5cdb1798 2005-10-29 devnull
1777 cbeb0b26 2006-04-01 devnull /* always make sure there's a terminator */
1778 5cdb1798 2005-10-29 devnull mimetypes[inuse].ext = 0;
1779 5cdb1798 2005-10-29 devnull }
1780 5cdb1798 2005-10-29 devnull Bterm(b);
1781 5cdb1798 2005-10-29 devnull }
1782 5cdb1798 2005-10-29 devnull
1783 5cdb1798 2005-10-29 devnull char*
1784 5cdb1798 2005-10-29 devnull estrdup(char *x)
1785 5cdb1798 2005-10-29 devnull {
1786 5cdb1798 2005-10-29 devnull x = strdup(x);
1787 5cdb1798 2005-10-29 devnull if(x == nil)
1788 5cdb1798 2005-10-29 devnull fatal("memory");
1789 5cdb1798 2005-10-29 devnull return x;
1790 5cdb1798 2005-10-29 devnull }
1791 5cdb1798 2005-10-29 devnull
1792 5cdb1798 2005-10-29 devnull void*
1793 5cdb1798 2005-10-29 devnull emalloc(int n)
1794 5cdb1798 2005-10-29 devnull {
1795 5cdb1798 2005-10-29 devnull void *x;
1796 5cdb1798 2005-10-29 devnull
1797 5cdb1798 2005-10-29 devnull x = malloc(n);
1798 5cdb1798 2005-10-29 devnull if(x == nil)
1799 5cdb1798 2005-10-29 devnull fatal("%r");
1800 5cdb1798 2005-10-29 devnull return x;
1801 5cdb1798 2005-10-29 devnull }
1802 5cdb1798 2005-10-29 devnull
1803 5cdb1798 2005-10-29 devnull void*
1804 5cdb1798 2005-10-29 devnull erealloc(void *x, int n)
1805 5cdb1798 2005-10-29 devnull {
1806 5cdb1798 2005-10-29 devnull x = realloc(x, n);
1807 5cdb1798 2005-10-29 devnull if(x == nil)
1808 5cdb1798 2005-10-29 devnull fatal("%r");
1809 5cdb1798 2005-10-29 devnull return x;
1810 5cdb1798 2005-10-29 devnull }
1811 5cdb1798 2005-10-29 devnull
1812 cbeb0b26 2006-04-01 devnull /* */
1813 cbeb0b26 2006-04-01 devnull /* Formatter for %" */
1814 cbeb0b26 2006-04-01 devnull /* Use double quotes to protect white space, frogs, \ and " */
1815 cbeb0b26 2006-04-01 devnull /* */
1816 5cdb1798 2005-10-29 devnull enum
1817 5cdb1798 2005-10-29 devnull {
1818 5cdb1798 2005-10-29 devnull Qok = 0,
1819 5cdb1798 2005-10-29 devnull Qquote,
1820 cbeb0b26 2006-04-01 devnull Qbackslash
1821 5cdb1798 2005-10-29 devnull };
1822 5cdb1798 2005-10-29 devnull
1823 5cdb1798 2005-10-29 devnull static int
1824 5cdb1798 2005-10-29 devnull needtoquote(Rune r)
1825 5cdb1798 2005-10-29 devnull {
1826 5cdb1798 2005-10-29 devnull if(r >= Runeself)
1827 5cdb1798 2005-10-29 devnull return Qquote;
1828 5cdb1798 2005-10-29 devnull if(r <= ' ')
1829 5cdb1798 2005-10-29 devnull return Qquote;
1830 5cdb1798 2005-10-29 devnull if(r=='\\' || r=='"')
1831 5cdb1798 2005-10-29 devnull return Qbackslash;
1832 5cdb1798 2005-10-29 devnull return Qok;
1833 5cdb1798 2005-10-29 devnull }
1834 5cdb1798 2005-10-29 devnull
1835 5cdb1798 2005-10-29 devnull int
1836 5cdb1798 2005-10-29 devnull doublequote(Fmt *f)
1837 5cdb1798 2005-10-29 devnull {
1838 5cdb1798 2005-10-29 devnull char *s, *t;
1839 5cdb1798 2005-10-29 devnull int w, quotes;
1840 5cdb1798 2005-10-29 devnull Rune r;
1841 5cdb1798 2005-10-29 devnull
1842 5cdb1798 2005-10-29 devnull s = va_arg(f->args, char*);
1843 5cdb1798 2005-10-29 devnull if(s == nil || *s == '\0')
1844 5cdb1798 2005-10-29 devnull return fmtstrcpy(f, "\"\"");
1845 5cdb1798 2005-10-29 devnull
1846 5cdb1798 2005-10-29 devnull quotes = 0;
1847 5cdb1798 2005-10-29 devnull for(t=s; *t; t+=w){
1848 5cdb1798 2005-10-29 devnull w = chartorune(&r, t);
1849 5cdb1798 2005-10-29 devnull quotes |= needtoquote(r);
1850 5cdb1798 2005-10-29 devnull }
1851 5cdb1798 2005-10-29 devnull if(quotes == 0)
1852 5cdb1798 2005-10-29 devnull return fmtstrcpy(f, s);
1853 5cdb1798 2005-10-29 devnull
1854 5cdb1798 2005-10-29 devnull fmtrune(f, '"');
1855 5cdb1798 2005-10-29 devnull for(t=s; *t; t+=w){
1856 5cdb1798 2005-10-29 devnull w = chartorune(&r, t);
1857 5cdb1798 2005-10-29 devnull if(needtoquote(r) == Qbackslash)
1858 5cdb1798 2005-10-29 devnull fmtrune(f, '\\');
1859 5cdb1798 2005-10-29 devnull fmtrune(f, r);
1860 5cdb1798 2005-10-29 devnull }
1861 5cdb1798 2005-10-29 devnull return fmtrune(f, '"');
1862 7ce2007c 2006-02-12 devnull }
1863 7ce2007c 2006-02-12 devnull
1864 7ce2007c 2006-02-12 devnull int
1865 7ce2007c 2006-02-12 devnull mountmail(void)
1866 7ce2007c 2006-02-12 devnull {
1867 7ce2007c 2006-02-12 devnull if(mailfs != nil)
1868 7ce2007c 2006-02-12 devnull return 0;
1869 7ce2007c 2006-02-12 devnull if((mailfs = nsmount("mail", nil)) == nil)
1870 7ce2007c 2006-02-12 devnull return -1;
1871 3d038c32 2006-03-31 devnull return 0;
1872 3d038c32 2006-03-31 devnull }
1873 3d038c32 2006-03-31 devnull
1874 3d038c32 2006-03-31 devnull int
1875 3d038c32 2006-03-31 devnull rfc2047fmt(Fmt *fmt)
1876 3d038c32 2006-03-31 devnull {
1877 3d038c32 2006-03-31 devnull char *s, *p;
1878 3d038c32 2006-03-31 devnull
1879 3d038c32 2006-03-31 devnull s = va_arg(fmt->args, char*);
1880 3d038c32 2006-03-31 devnull if(s == nil)
1881 3d038c32 2006-03-31 devnull return fmtstrcpy(fmt, "");
1882 3d038c32 2006-03-31 devnull for(p=s; *p; p++)
1883 3d038c32 2006-03-31 devnull if((uchar)*p >= 0x80)
1884 3d038c32 2006-03-31 devnull goto hard;
1885 3d038c32 2006-03-31 devnull return fmtstrcpy(fmt, s);
1886 3d038c32 2006-03-31 devnull
1887 3d038c32 2006-03-31 devnull hard:
1888 3d038c32 2006-03-31 devnull fmtprint(fmt, "=?utf-8?q?");
1889 3d038c32 2006-03-31 devnull for(p=s; *p; p++){
1890 3d038c32 2006-03-31 devnull if(*p == ' ')
1891 3d038c32 2006-03-31 devnull fmtrune(fmt, '_');
1892 3d038c32 2006-03-31 devnull else if(*p == '_' || *p == '\t' || *p == '=' || *p == '?' || (uchar)*p >= 0x80)
1893 3d038c32 2006-03-31 devnull fmtprint(fmt, "=%.2uX", (uchar)*p);
1894 3d038c32 2006-03-31 devnull else
1895 3d038c32 2006-03-31 devnull fmtrune(fmt, (uchar)*p);
1896 3d038c32 2006-03-31 devnull }
1897 3d038c32 2006-03-31 devnull fmtprint(fmt, "?=");
1898 7ce2007c 2006-02-12 devnull return 0;
1899 5cdb1798 2005-10-29 devnull }
1900 3d038c32 2006-03-31 devnull
1901 3d038c32 2006-03-31 devnull char*
1902 3d038c32 2006-03-31 devnull mksubject(char *line)
1903 3d038c32 2006-03-31 devnull {
1904 3d038c32 2006-03-31 devnull char *p, *q;
1905 3d038c32 2006-03-31 devnull static char buf[1024];
1906 3d038c32 2006-03-31 devnull
1907 3d038c32 2006-03-31 devnull p = strchr(line, ':')+1;
1908 3d038c32 2006-03-31 devnull while(*p == ' ')
1909 3d038c32 2006-03-31 devnull p++;
1910 3d038c32 2006-03-31 devnull for(q=p; *q; q++)
1911 3d038c32 2006-03-31 devnull if((uchar)*q >= 0x80)
1912 3d038c32 2006-03-31 devnull goto hard;
1913 3d038c32 2006-03-31 devnull return line;
1914 3d038c32 2006-03-31 devnull
1915 3d038c32 2006-03-31 devnull hard:
1916 3d038c32 2006-03-31 devnull snprint(buf, sizeof buf, "Subject: %U", p);
1917 3d038c32 2006-03-31 devnull return buf;
1918 3d038c32 2006-03-31 devnull }