Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include <ctype.h>
3 5cdb1798 2005-10-29 devnull #include <plumb.h>
4 5cdb1798 2005-10-29 devnull #include <9pclient.h>
5 5cdb1798 2005-10-29 devnull #include <thread.h>
6 5cdb1798 2005-10-29 devnull
7 7e61af51 2006-02-12 devnull #define system nedsystem
8 25c82339 2006-05-21 devnull #define rcmd nedrcmd
9 7e61af51 2006-02-12 devnull
10 5cdb1798 2005-10-29 devnull typedef struct Message Message;
11 5cdb1798 2005-10-29 devnull typedef struct Ctype Ctype;
12 5cdb1798 2005-10-29 devnull typedef struct Cmd Cmd;
13 5cdb1798 2005-10-29 devnull
14 5cdb1798 2005-10-29 devnull char root[Pathlen];
15 5cdb1798 2005-10-29 devnull char mbname[Elemlen];
16 5cdb1798 2005-10-29 devnull int rootlen;
17 5cdb1798 2005-10-29 devnull int didopen;
18 5cdb1798 2005-10-29 devnull char *user;
19 5cdb1798 2005-10-29 devnull char wd[2048];
20 5cdb1798 2005-10-29 devnull String *mbpath;
21 5cdb1798 2005-10-29 devnull int natural;
22 5cdb1798 2005-10-29 devnull int doflush;
23 5cdb1798 2005-10-29 devnull
24 5cdb1798 2005-10-29 devnull int interrupted;
25 5cdb1798 2005-10-29 devnull
26 5cdb1798 2005-10-29 devnull struct Message {
27 5cdb1798 2005-10-29 devnull Message *next;
28 5cdb1798 2005-10-29 devnull Message *prev;
29 5cdb1798 2005-10-29 devnull Message *cmd;
30 5cdb1798 2005-10-29 devnull Message *child;
31 5cdb1798 2005-10-29 devnull Message *parent;
32 5cdb1798 2005-10-29 devnull String *path;
33 5cdb1798 2005-10-29 devnull int id;
34 5cdb1798 2005-10-29 devnull int len;
35 cbeb0b26 2006-04-01 devnull int fileno; /* number of directory */
36 5cdb1798 2005-10-29 devnull String *info;
37 5cdb1798 2005-10-29 devnull char *from;
38 5cdb1798 2005-10-29 devnull char *to;
39 5cdb1798 2005-10-29 devnull char *cc;
40 5cdb1798 2005-10-29 devnull char *replyto;
41 5cdb1798 2005-10-29 devnull char *date;
42 5cdb1798 2005-10-29 devnull char *subject;
43 5cdb1798 2005-10-29 devnull char *type;
44 5cdb1798 2005-10-29 devnull char *disposition;
45 5cdb1798 2005-10-29 devnull char *filename;
46 5cdb1798 2005-10-29 devnull char deleted;
47 5cdb1798 2005-10-29 devnull char stored;
48 5cdb1798 2005-10-29 devnull };
49 5cdb1798 2005-10-29 devnull
50 5cdb1798 2005-10-29 devnull Message top;
51 5cdb1798 2005-10-29 devnull
52 5cdb1798 2005-10-29 devnull struct Ctype {
53 5cdb1798 2005-10-29 devnull char *type;
54 5cdb1798 2005-10-29 devnull char *ext;
55 5cdb1798 2005-10-29 devnull int display;
56 5cdb1798 2005-10-29 devnull char *plumbdest;
57 5cdb1798 2005-10-29 devnull Ctype *next;
58 5cdb1798 2005-10-29 devnull };
59 5cdb1798 2005-10-29 devnull
60 5cdb1798 2005-10-29 devnull Ctype ctype[] = {
61 5cdb1798 2005-10-29 devnull { "text/plain", "txt", 1, 0 },
62 5cdb1798 2005-10-29 devnull { "text/html", "htm", 1, 0 },
63 5cdb1798 2005-10-29 devnull { "text/html", "html", 1, 0 },
64 5cdb1798 2005-10-29 devnull { "text/tab-separated-values", "tsv", 1, 0 },
65 5cdb1798 2005-10-29 devnull { "text/richtext", "rtx", 1, 0 },
66 5cdb1798 2005-10-29 devnull { "text/rtf", "rtf", 1, 0 },
67 5cdb1798 2005-10-29 devnull { "text", "txt", 1, 0 },
68 5cdb1798 2005-10-29 devnull { "message/rfc822", "msg", 0, 0 },
69 7e61af51 2006-02-12 devnull { "message/delivery-status", "txt", 1, 0 },
70 5cdb1798 2005-10-29 devnull { "image/bmp", "bmp", 0, "image" },
71 5cdb1798 2005-10-29 devnull { "image/jpeg", "jpg", 0, "image" },
72 5cdb1798 2005-10-29 devnull { "image/gif", "gif", 0, "image" },
73 7e61af51 2006-02-12 devnull { "image/png", "png", 0, "image" },
74 5cdb1798 2005-10-29 devnull { "application/pdf", "pdf", 0, "postscript" },
75 5cdb1798 2005-10-29 devnull { "application/postscript", "ps", 0, "postscript" },
76 5cdb1798 2005-10-29 devnull { "application/", 0, 0, 0 },
77 5cdb1798 2005-10-29 devnull { "image/", 0, 0, 0 },
78 5cdb1798 2005-10-29 devnull { "multipart/", "mul", 0, 0 },
79 5cdb1798 2005-10-29 devnull
80 5cdb1798 2005-10-29 devnull };
81 5cdb1798 2005-10-29 devnull
82 5cdb1798 2005-10-29 devnull Message* acmd(Cmd*, Message*);
83 5cdb1798 2005-10-29 devnull Message* bcmd(Cmd*, Message*);
84 5cdb1798 2005-10-29 devnull Message* dcmd(Cmd*, Message*);
85 5cdb1798 2005-10-29 devnull Message* eqcmd(Cmd*, Message*);
86 5cdb1798 2005-10-29 devnull Message* hcmd(Cmd*, Message*);
87 5cdb1798 2005-10-29 devnull Message* Hcmd(Cmd*, Message*);
88 5cdb1798 2005-10-29 devnull Message* helpcmd(Cmd*, Message*);
89 5cdb1798 2005-10-29 devnull Message* icmd(Cmd*, Message*);
90 5cdb1798 2005-10-29 devnull Message* pcmd(Cmd*, Message*);
91 5cdb1798 2005-10-29 devnull Message* qcmd(Cmd*, Message*);
92 5cdb1798 2005-10-29 devnull Message* rcmd(Cmd*, Message*);
93 5cdb1798 2005-10-29 devnull Message* scmd(Cmd*, Message*);
94 5cdb1798 2005-10-29 devnull Message* ucmd(Cmd*, Message*);
95 5cdb1798 2005-10-29 devnull Message* wcmd(Cmd*, Message*);
96 5cdb1798 2005-10-29 devnull Message* xcmd(Cmd*, Message*);
97 5cdb1798 2005-10-29 devnull Message* ycmd(Cmd*, Message*);
98 5cdb1798 2005-10-29 devnull Message* pipecmd(Cmd*, Message*);
99 5cdb1798 2005-10-29 devnull Message* rpipecmd(Cmd*, Message*);
100 5cdb1798 2005-10-29 devnull Message* bangcmd(Cmd*, Message*);
101 5cdb1798 2005-10-29 devnull Message* Pcmd(Cmd*, Message*);
102 5cdb1798 2005-10-29 devnull Message* mcmd(Cmd*, Message*);
103 5cdb1798 2005-10-29 devnull Message* fcmd(Cmd*, Message*);
104 5cdb1798 2005-10-29 devnull Message* quotecmd(Cmd*, Message*);
105 5cdb1798 2005-10-29 devnull
106 5cdb1798 2005-10-29 devnull struct {
107 5cdb1798 2005-10-29 devnull char *cmd;
108 5cdb1798 2005-10-29 devnull int args;
109 5cdb1798 2005-10-29 devnull Message* (*f)(Cmd*, Message*);
110 5cdb1798 2005-10-29 devnull char *help;
111 5cdb1798 2005-10-29 devnull } cmdtab[] = {
112 5cdb1798 2005-10-29 devnull { "a", 1, acmd, "a reply to sender and recipients" },
113 5cdb1798 2005-10-29 devnull { "A", 1, acmd, "A reply to sender and recipients with copy" },
114 5cdb1798 2005-10-29 devnull { "b", 0, bcmd, "b print the next 10 headers" },
115 5cdb1798 2005-10-29 devnull { "d", 0, dcmd, "d mark for deletion" },
116 5cdb1798 2005-10-29 devnull { "f", 0, fcmd, "f file message by from address" },
117 5cdb1798 2005-10-29 devnull { "h", 0, hcmd, "h print elided message summary (,h for all)" },
118 5cdb1798 2005-10-29 devnull { "help", 0, helpcmd, "help print this info" },
119 5cdb1798 2005-10-29 devnull { "H", 0, Hcmd, "H print message's MIME structure " },
120 5cdb1798 2005-10-29 devnull { "i", 0, icmd, "i incorporate new mail" },
121 5cdb1798 2005-10-29 devnull { "m", 1, mcmd, "m addr forward mail" },
122 5cdb1798 2005-10-29 devnull { "M", 1, mcmd, "M addr forward mail with message" },
123 5cdb1798 2005-10-29 devnull { "p", 0, pcmd, "p print the processed message" },
124 5cdb1798 2005-10-29 devnull { "P", 0, Pcmd, "P print the raw message" },
125 5cdb1798 2005-10-29 devnull { "\"", 0, quotecmd, "\" print a quoted version of msg" },
126 5cdb1798 2005-10-29 devnull { "q", 0, qcmd, "q exit and remove all deleted mail" },
127 5cdb1798 2005-10-29 devnull { "r", 1, rcmd, "r [addr] reply to sender plus any addrs specified" },
128 5cdb1798 2005-10-29 devnull { "rf", 1, rcmd, "rf [addr]file message and reply" },
129 5cdb1798 2005-10-29 devnull { "R", 1, rcmd, "R [addr] reply including copy of message" },
130 5cdb1798 2005-10-29 devnull { "Rf", 1, rcmd, "Rf [addr]file message and reply with copy" },
131 5cdb1798 2005-10-29 devnull { "s", 1, scmd, "s file append raw message to file" },
132 5cdb1798 2005-10-29 devnull { "u", 0, ucmd, "u remove deletion mark" },
133 5cdb1798 2005-10-29 devnull { "w", 1, wcmd, "w file store message contents as file" },
134 5cdb1798 2005-10-29 devnull { "x", 0, xcmd, "x exit without flushing deleted messages" },
135 5cdb1798 2005-10-29 devnull { "y", 0, ycmd, "y synchronize with mail box" },
136 5cdb1798 2005-10-29 devnull { "=", 1, eqcmd, "= print current message number" },
137 5cdb1798 2005-10-29 devnull { "|", 1, pipecmd, "|cmd pipe message body to a command" },
138 5cdb1798 2005-10-29 devnull { "||", 1, rpipecmd, "||cmd pipe raw message to a command" },
139 5cdb1798 2005-10-29 devnull { "!", 1, bangcmd, "!cmd run a command" },
140 cbeb0b26 2006-04-01 devnull { nil, 0, nil, nil }
141 5cdb1798 2005-10-29 devnull };
142 5cdb1798 2005-10-29 devnull
143 5cdb1798 2005-10-29 devnull enum
144 5cdb1798 2005-10-29 devnull {
145 cbeb0b26 2006-04-01 devnull NARG= 32
146 5cdb1798 2005-10-29 devnull };
147 5cdb1798 2005-10-29 devnull
148 5cdb1798 2005-10-29 devnull struct Cmd {
149 5cdb1798 2005-10-29 devnull Message *msgs;
150 5cdb1798 2005-10-29 devnull Message *(*f)(Cmd*, Message*);
151 5cdb1798 2005-10-29 devnull int an;
152 5cdb1798 2005-10-29 devnull char *av[NARG];
153 5cdb1798 2005-10-29 devnull int delete;
154 5cdb1798 2005-10-29 devnull };
155 5cdb1798 2005-10-29 devnull
156 5cdb1798 2005-10-29 devnull Biobuf out;
157 5cdb1798 2005-10-29 devnull int startedfs;
158 5cdb1798 2005-10-29 devnull int reverse;
159 5cdb1798 2005-10-29 devnull int longestfrom = 12;
160 5cdb1798 2005-10-29 devnull
161 5cdb1798 2005-10-29 devnull String* file2string(String*, char*);
162 5cdb1798 2005-10-29 devnull int dir2message(Message*, int);
163 5cdb1798 2005-10-29 devnull int filelen(String*, char*);
164 5cdb1798 2005-10-29 devnull String* extendpath(String*, char*);
165 5cdb1798 2005-10-29 devnull void snprintheader(char*, int, Message*);
166 5cdb1798 2005-10-29 devnull void cracktime(char*, char*, int);
167 5cdb1798 2005-10-29 devnull int cistrncmp(char*, char*, int);
168 5cdb1798 2005-10-29 devnull int cistrcmp(char*, char*);
169 5cdb1798 2005-10-29 devnull Reprog* parsesearch(char**);
170 5cdb1798 2005-10-29 devnull char* parseaddr(char**, Message*, Message*, Message*, Message**);
171 5cdb1798 2005-10-29 devnull char* parsecmd(char*, Cmd*, Message*, Message*);
172 5cdb1798 2005-10-29 devnull char* readline(char*, char*, int);
173 5cdb1798 2005-10-29 devnull void messagecount(Message*);
174 7e61af51 2006-02-12 devnull void system(char*, char**, int);
175 5cdb1798 2005-10-29 devnull void mkid(String*, Message*);
176 5cdb1798 2005-10-29 devnull int switchmb(char*, char*);
177 5cdb1798 2005-10-29 devnull void closemb(void);
178 5cdb1798 2005-10-29 devnull int lineize(char*, char**, int);
179 5cdb1798 2005-10-29 devnull int rawsearch(Message*, Reprog*);
180 5cdb1798 2005-10-29 devnull Message* dosingleton(Message*, char*);
181 5cdb1798 2005-10-29 devnull String* rooted(String*);
182 5cdb1798 2005-10-29 devnull int plumb(Message*, Ctype*);
183 5cdb1798 2005-10-29 devnull String* addrecolon(char*);
184 5cdb1798 2005-10-29 devnull void exitfs(char*);
185 5cdb1798 2005-10-29 devnull Message* flushdeleted(Message*);
186 5cdb1798 2005-10-29 devnull
187 7e61af51 2006-02-12 devnull CFsys *mailfs;
188 5cdb1798 2005-10-29 devnull
189 5cdb1798 2005-10-29 devnull void
190 5cdb1798 2005-10-29 devnull usage(void)
191 5cdb1798 2005-10-29 devnull {
192 5cdb1798 2005-10-29 devnull fprint(2, "usage: %s [-nr] [-f mailfile] [-s mailfile]\n", argv0);
193 5cdb1798 2005-10-29 devnull fprint(2, " %s -c dir\n", argv0);
194 7e61af51 2006-02-12 devnull threadexitsall("usage");
195 5cdb1798 2005-10-29 devnull }
196 5cdb1798 2005-10-29 devnull
197 5cdb1798 2005-10-29 devnull void
198 7e61af51 2006-02-12 devnull catchnote(void *x, char *note)
199 5cdb1798 2005-10-29 devnull {
200 7e61af51 2006-02-12 devnull USED(x);
201 7e61af51 2006-02-12 devnull
202 5cdb1798 2005-10-29 devnull if(strstr(note, "interrupt") != nil){
203 5cdb1798 2005-10-29 devnull interrupted = 1;
204 5cdb1798 2005-10-29 devnull noted(NCONT);
205 5cdb1798 2005-10-29 devnull }
206 5cdb1798 2005-10-29 devnull noted(NDFLT);
207 5cdb1798 2005-10-29 devnull }
208 5cdb1798 2005-10-29 devnull
209 5cdb1798 2005-10-29 devnull char *
210 5cdb1798 2005-10-29 devnull plural(int n)
211 5cdb1798 2005-10-29 devnull {
212 5cdb1798 2005-10-29 devnull if (n == 1)
213 5cdb1798 2005-10-29 devnull return "";
214 5cdb1798 2005-10-29 devnull
215 5cdb1798 2005-10-29 devnull return "s";
216 5cdb1798 2005-10-29 devnull }
217 5cdb1798 2005-10-29 devnull
218 5cdb1798 2005-10-29 devnull void
219 5cdb1798 2005-10-29 devnull threadmain(int argc, char **argv)
220 5cdb1798 2005-10-29 devnull {
221 5cdb1798 2005-10-29 devnull Message *cur, *m, *x;
222 5cdb1798 2005-10-29 devnull char cmdline[4*1024];
223 5cdb1798 2005-10-29 devnull Cmd cmd;
224 5cdb1798 2005-10-29 devnull Ctype *cp;
225 5cdb1798 2005-10-29 devnull char *err;
226 5cdb1798 2005-10-29 devnull int n, cflag;
227 5cdb1798 2005-10-29 devnull String *prompt;
228 b2bf1414 2008-07-10 rsc char *file, *singleton, *service;
229 5cdb1798 2005-10-29 devnull
230 5cdb1798 2005-10-29 devnull Binit(&out, 1, OWRITE);
231 5cdb1798 2005-10-29 devnull
232 5cdb1798 2005-10-29 devnull file = nil;
233 5cdb1798 2005-10-29 devnull singleton = nil;
234 5cdb1798 2005-10-29 devnull reverse = 1;
235 5cdb1798 2005-10-29 devnull cflag = 0;
236 b2bf1414 2008-07-10 rsc service = "mail";
237 5cdb1798 2005-10-29 devnull ARGBEGIN {
238 b2bf1414 2008-07-10 rsc case 'S':
239 b2bf1414 2008-07-10 rsc service = EARGF(usage());
240 b2bf1414 2008-07-10 rsc break;
241 5cdb1798 2005-10-29 devnull case 'c':
242 5cdb1798 2005-10-29 devnull cflag = 1;
243 5cdb1798 2005-10-29 devnull break;
244 5cdb1798 2005-10-29 devnull case 'f':
245 5cdb1798 2005-10-29 devnull file = EARGF(usage());
246 5cdb1798 2005-10-29 devnull break;
247 5cdb1798 2005-10-29 devnull case 's':
248 5cdb1798 2005-10-29 devnull singleton = EARGF(usage());
249 5cdb1798 2005-10-29 devnull break;
250 5cdb1798 2005-10-29 devnull case 'r':
251 5cdb1798 2005-10-29 devnull reverse = 0;
252 5cdb1798 2005-10-29 devnull break;
253 5cdb1798 2005-10-29 devnull case 'n':
254 5cdb1798 2005-10-29 devnull natural = 1;
255 5cdb1798 2005-10-29 devnull reverse = 0;
256 5cdb1798 2005-10-29 devnull break;
257 5cdb1798 2005-10-29 devnull default:
258 5cdb1798 2005-10-29 devnull usage();
259 5cdb1798 2005-10-29 devnull break;
260 5cdb1798 2005-10-29 devnull } ARGEND;
261 5cdb1798 2005-10-29 devnull
262 5cdb1798 2005-10-29 devnull user = getlog();
263 5cdb1798 2005-10-29 devnull if(user == nil || *user == 0)
264 5cdb1798 2005-10-29 devnull sysfatal("can't read user name");
265 5cdb1798 2005-10-29 devnull
266 5cdb1798 2005-10-29 devnull if(cflag){
267 5cdb1798 2005-10-29 devnull if(argc > 0)
268 5cdb1798 2005-10-29 devnull creatembox(user, argv[0]);
269 5cdb1798 2005-10-29 devnull else
270 5cdb1798 2005-10-29 devnull creatembox(user, nil);
271 7e61af51 2006-02-12 devnull threadexitsall(0);
272 5cdb1798 2005-10-29 devnull }
273 5cdb1798 2005-10-29 devnull
274 5cdb1798 2005-10-29 devnull if(argc)
275 5cdb1798 2005-10-29 devnull usage();
276 b2bf1414 2008-07-10 rsc if((mailfs = nsmount(service, nil)) == nil)
277 b2bf1414 2008-07-10 rsc sysfatal("cannot mount %s: %r", service);
278 5cdb1798 2005-10-29 devnull
279 5cdb1798 2005-10-29 devnull switchmb(file, singleton);
280 5cdb1798 2005-10-29 devnull
281 5cdb1798 2005-10-29 devnull top.path = s_copy(root);
282 5cdb1798 2005-10-29 devnull
283 5cdb1798 2005-10-29 devnull for(cp = ctype; cp < ctype+nelem(ctype)-1; cp++)
284 5cdb1798 2005-10-29 devnull cp->next = cp+1;
285 5cdb1798 2005-10-29 devnull
286 5cdb1798 2005-10-29 devnull if(singleton != nil){
287 5cdb1798 2005-10-29 devnull cur = dosingleton(&top, singleton);
288 5cdb1798 2005-10-29 devnull if(cur == nil){
289 5cdb1798 2005-10-29 devnull Bprint(&out, "no message\n");
290 5cdb1798 2005-10-29 devnull exitfs(0);
291 5cdb1798 2005-10-29 devnull }
292 5cdb1798 2005-10-29 devnull pcmd(nil, cur);
293 5cdb1798 2005-10-29 devnull } else {
294 5cdb1798 2005-10-29 devnull cur = &top;
295 5cdb1798 2005-10-29 devnull n = dir2message(&top, reverse);
296 5cdb1798 2005-10-29 devnull if(n < 0)
297 5cdb1798 2005-10-29 devnull sysfatal("can't read %s", s_to_c(top.path));
298 5cdb1798 2005-10-29 devnull Bprint(&out, "%d message%s\n", n, plural(n));
299 5cdb1798 2005-10-29 devnull }
300 5cdb1798 2005-10-29 devnull
301 5cdb1798 2005-10-29 devnull
302 5cdb1798 2005-10-29 devnull notify(catchnote);
303 5cdb1798 2005-10-29 devnull prompt = s_new();
304 5cdb1798 2005-10-29 devnull for(;;){
305 5cdb1798 2005-10-29 devnull s_reset(prompt);
306 5cdb1798 2005-10-29 devnull if(cur == &top)
307 5cdb1798 2005-10-29 devnull s_append(prompt, ": ");
308 5cdb1798 2005-10-29 devnull else {
309 5cdb1798 2005-10-29 devnull mkid(prompt, cur);
310 5cdb1798 2005-10-29 devnull s_append(prompt, ": ");
311 5cdb1798 2005-10-29 devnull }
312 5cdb1798 2005-10-29 devnull
313 cbeb0b26 2006-04-01 devnull /* leave space at the end of cmd line in case parsecmd needs to */
314 cbeb0b26 2006-04-01 devnull /* add a space after a '|' or '!' */
315 5cdb1798 2005-10-29 devnull if(readline(s_to_c(prompt), cmdline, sizeof(cmdline)-1) == nil)
316 5cdb1798 2005-10-29 devnull break;
317 5cdb1798 2005-10-29 devnull err = parsecmd(cmdline, &cmd, top.child, cur);
318 5cdb1798 2005-10-29 devnull if(err != nil){
319 5cdb1798 2005-10-29 devnull Bprint(&out, "!%s\n", err);
320 5cdb1798 2005-10-29 devnull continue;
321 5cdb1798 2005-10-29 devnull }
322 5cdb1798 2005-10-29 devnull if(singleton != nil && cmd.f == icmd){
323 5cdb1798 2005-10-29 devnull Bprint(&out, "!illegal command\n");
324 5cdb1798 2005-10-29 devnull continue;
325 5cdb1798 2005-10-29 devnull }
326 5cdb1798 2005-10-29 devnull interrupted = 0;
327 5cdb1798 2005-10-29 devnull if(cmd.msgs == nil || cmd.msgs == &top){
328 5cdb1798 2005-10-29 devnull x = (*cmd.f)(&cmd, &top);
329 5cdb1798 2005-10-29 devnull if(x != nil)
330 5cdb1798 2005-10-29 devnull cur = x;
331 5cdb1798 2005-10-29 devnull } else for(m = cmd.msgs; m != nil; m = m->cmd){
332 5cdb1798 2005-10-29 devnull x = m;
333 5cdb1798 2005-10-29 devnull if(cmd.delete){
334 5cdb1798 2005-10-29 devnull dcmd(&cmd, x);
335 5cdb1798 2005-10-29 devnull
336 cbeb0b26 2006-04-01 devnull /* dp acts differently than all other commands */
337 cbeb0b26 2006-04-01 devnull /* since its an old lesk idiom that people love. */
338 cbeb0b26 2006-04-01 devnull /* it deletes the current message, moves the current */
339 cbeb0b26 2006-04-01 devnull /* pointer ahead one and prints. */
340 5cdb1798 2005-10-29 devnull if(cmd.f == pcmd){
341 5cdb1798 2005-10-29 devnull if(x->next == nil){
342 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
343 5cdb1798 2005-10-29 devnull cur = x;
344 5cdb1798 2005-10-29 devnull break;
345 5cdb1798 2005-10-29 devnull } else
346 5cdb1798 2005-10-29 devnull x = x->next;
347 5cdb1798 2005-10-29 devnull }
348 5cdb1798 2005-10-29 devnull }
349 5cdb1798 2005-10-29 devnull x = (*cmd.f)(&cmd, x);
350 5cdb1798 2005-10-29 devnull if(x != nil)
351 5cdb1798 2005-10-29 devnull cur = x;
352 5cdb1798 2005-10-29 devnull if(interrupted)
353 5cdb1798 2005-10-29 devnull break;
354 5cdb1798 2005-10-29 devnull if(singleton != nil && (cmd.delete || cmd.f == dcmd))
355 5cdb1798 2005-10-29 devnull qcmd(nil, nil);
356 5cdb1798 2005-10-29 devnull }
357 5cdb1798 2005-10-29 devnull if(doflush)
358 5cdb1798 2005-10-29 devnull cur = flushdeleted(cur);
359 5cdb1798 2005-10-29 devnull }
360 5cdb1798 2005-10-29 devnull qcmd(nil, nil);
361 1ea614ff 2006-02-15 devnull }
362 1ea614ff 2006-02-15 devnull
363 1ea614ff 2006-02-15 devnull static char*
364 1ea614ff 2006-02-15 devnull mkaddrs(char *t)
365 1ea614ff 2006-02-15 devnull {
366 1ea614ff 2006-02-15 devnull int i, nf, inquote;
367 1ea614ff 2006-02-15 devnull char **f, *s;
368 1ea614ff 2006-02-15 devnull Fmt fmt;
369 1ea614ff 2006-02-15 devnull
370 1ea614ff 2006-02-15 devnull inquote = 0;
371 1ea614ff 2006-02-15 devnull nf = 2;
372 1ea614ff 2006-02-15 devnull for(s=t; *s; s++){
373 1ea614ff 2006-02-15 devnull if(*s == '\'')
374 1ea614ff 2006-02-15 devnull inquote = !inquote;
375 1ea614ff 2006-02-15 devnull if(*s == ' ' && !inquote)
376 1ea614ff 2006-02-15 devnull nf++;
377 1ea614ff 2006-02-15 devnull }
378 1ea614ff 2006-02-15 devnull f = malloc(nf*sizeof f[0]);
379 1ea614ff 2006-02-15 devnull if(f == nil)
380 1ea614ff 2006-02-15 devnull return nil;
381 1ea614ff 2006-02-15 devnull nf = tokenize(t, f, nf);
382 1ea614ff 2006-02-15 devnull fmtstrinit(&fmt);
383 1ea614ff 2006-02-15 devnull for(i=0; i+1<nf; i+=2){
384 1ea614ff 2006-02-15 devnull if(i > 0)
385 1ea614ff 2006-02-15 devnull fmtprint(&fmt, " ");
386 cbeb0b26 2006-04-01 devnull /* if(f[i][0] == 0 || strcmp(f[i], f[i+1]) == 0) */
387 1ea614ff 2006-02-15 devnull fmtprint(&fmt, "%s", f[i+1]);
388 cbeb0b26 2006-04-01 devnull /* else */
389 cbeb0b26 2006-04-01 devnull /* fmtprint(&fmt, "%s <%s>", f[i], f[i+1]); */
390 1ea614ff 2006-02-15 devnull }
391 1ea614ff 2006-02-15 devnull free(f);
392 1ea614ff 2006-02-15 devnull return fmtstrflush(&fmt);
393 5cdb1798 2005-10-29 devnull }
394 5cdb1798 2005-10-29 devnull
395 cbeb0b26 2006-04-01 devnull /* */
396 cbeb0b26 2006-04-01 devnull /* read the message info */
397 cbeb0b26 2006-04-01 devnull /* */
398 5cdb1798 2005-10-29 devnull Message*
399 5cdb1798 2005-10-29 devnull file2message(Message *parent, char *name)
400 5cdb1798 2005-10-29 devnull {
401 5cdb1798 2005-10-29 devnull Message *m;
402 5cdb1798 2005-10-29 devnull String *path;
403 7e61af51 2006-02-12 devnull char *f[30], *s, *t;
404 7e61af51 2006-02-12 devnull int i, nf;
405 7e61af51 2006-02-12 devnull
406 5cdb1798 2005-10-29 devnull m = mallocz(sizeof(Message), 1);
407 5cdb1798 2005-10-29 devnull if(m == nil)
408 5cdb1798 2005-10-29 devnull return nil;
409 5cdb1798 2005-10-29 devnull m->path = path = extendpath(parent->path, name);
410 5cdb1798 2005-10-29 devnull m->fileno = atoi(name);
411 5cdb1798 2005-10-29 devnull m->info = file2string(path, "info");
412 7e61af51 2006-02-12 devnull m->from = "";
413 7e61af51 2006-02-12 devnull m->to = "";
414 7e61af51 2006-02-12 devnull m->cc = "";
415 7e61af51 2006-02-12 devnull m->replyto = "";
416 7e61af51 2006-02-12 devnull m->date = "";
417 7e61af51 2006-02-12 devnull m->subject = "";
418 7e61af51 2006-02-12 devnull m->type = "";
419 7e61af51 2006-02-12 devnull m->disposition = "";
420 7e61af51 2006-02-12 devnull m->filename = "";
421 7e61af51 2006-02-12 devnull nf = lineize(s_to_c(m->info), f, nelem(f));
422 7e61af51 2006-02-12 devnull for(i=0; i<nf; i++){
423 7e61af51 2006-02-12 devnull s = f[i];
424 7e61af51 2006-02-12 devnull t = strchr(f[i], ' ');
425 7e61af51 2006-02-12 devnull if(t == nil)
426 7e61af51 2006-02-12 devnull continue;
427 7e61af51 2006-02-12 devnull *t++ = 0;
428 7e61af51 2006-02-12 devnull
429 7e61af51 2006-02-12 devnull if(strcmp(s, "from") == 0)
430 1ea614ff 2006-02-15 devnull m->from = mkaddrs(t);
431 7e61af51 2006-02-12 devnull else if(strcmp(s, "to") == 0)
432 1ea614ff 2006-02-15 devnull m->to = mkaddrs(t);
433 7e61af51 2006-02-12 devnull else if(strcmp(s, "cc") == 0)
434 1ea614ff 2006-02-15 devnull m->cc = mkaddrs(t);
435 7e61af51 2006-02-12 devnull else if(strcmp(s, "replyto") == 0)
436 1ea614ff 2006-02-15 devnull m->replyto = mkaddrs(t);
437 7e61af51 2006-02-12 devnull else if(strcmp(s, "unixdate") == 0 && (t=strchr(t, ' ')) != nil)
438 7e61af51 2006-02-12 devnull m->date = t;
439 7e61af51 2006-02-12 devnull else if(strcmp(s, "subject") == 0)
440 7e61af51 2006-02-12 devnull m->subject = t;
441 7e61af51 2006-02-12 devnull else if(strcmp(s, "type") == 0)
442 7e61af51 2006-02-12 devnull m->type = t;
443 7e61af51 2006-02-12 devnull else if(strcmp(s, "disposition") == 0)
444 7e61af51 2006-02-12 devnull m->disposition = t;
445 7e61af51 2006-02-12 devnull else if(strcmp(s, "filename") == 0)
446 7e61af51 2006-02-12 devnull m->filename = t;
447 7e61af51 2006-02-12 devnull }
448 5cdb1798 2005-10-29 devnull m->len = filelen(path, "raw");
449 5cdb1798 2005-10-29 devnull if(strstr(m->type, "multipart") != nil || strcmp(m->type, "message/rfc822") == 0)
450 5cdb1798 2005-10-29 devnull dir2message(m, 0);
451 5cdb1798 2005-10-29 devnull m->parent = parent;
452 5cdb1798 2005-10-29 devnull
453 5cdb1798 2005-10-29 devnull return m;
454 5cdb1798 2005-10-29 devnull }
455 5cdb1798 2005-10-29 devnull
456 5cdb1798 2005-10-29 devnull void
457 5cdb1798 2005-10-29 devnull freemessage(Message *m)
458 5cdb1798 2005-10-29 devnull {
459 5cdb1798 2005-10-29 devnull Message *nm, *next;
460 5cdb1798 2005-10-29 devnull
461 5cdb1798 2005-10-29 devnull for(nm = m->child; nm != nil; nm = next){
462 5cdb1798 2005-10-29 devnull next = nm->next;
463 5cdb1798 2005-10-29 devnull freemessage(nm);
464 5cdb1798 2005-10-29 devnull }
465 5cdb1798 2005-10-29 devnull s_free(m->path);
466 5cdb1798 2005-10-29 devnull s_free(m->info);
467 5cdb1798 2005-10-29 devnull free(m);
468 5cdb1798 2005-10-29 devnull }
469 5cdb1798 2005-10-29 devnull
470 cbeb0b26 2006-04-01 devnull /* */
471 cbeb0b26 2006-04-01 devnull /* read a directory into a list of messages */
472 cbeb0b26 2006-04-01 devnull /* */
473 5cdb1798 2005-10-29 devnull int
474 5cdb1798 2005-10-29 devnull dir2message(Message *parent, int reverse)
475 5cdb1798 2005-10-29 devnull {
476 5cdb1798 2005-10-29 devnull int i, n, highest, newmsgs;
477 7e61af51 2006-02-12 devnull CFid *fd;
478 5cdb1798 2005-10-29 devnull
479 5cdb1798 2005-10-29 devnull Dir *d;
480 5cdb1798 2005-10-29 devnull Message *first, *last, *m;
481 5cdb1798 2005-10-29 devnull
482 7e61af51 2006-02-12 devnull fd = fsopen(mailfs, s_to_c(parent->path), OREAD);
483 7e61af51 2006-02-12 devnull if(fd == nil)
484 5cdb1798 2005-10-29 devnull return -1;
485 5cdb1798 2005-10-29 devnull
486 cbeb0b26 2006-04-01 devnull /* count current entries */
487 5cdb1798 2005-10-29 devnull first = parent->child;
488 5cdb1798 2005-10-29 devnull highest = newmsgs = 0;
489 5cdb1798 2005-10-29 devnull for(last = parent->child; last != nil && last->next != nil; last = last->next)
490 5cdb1798 2005-10-29 devnull if(last->fileno > highest)
491 5cdb1798 2005-10-29 devnull highest = last->fileno;
492 5cdb1798 2005-10-29 devnull if(last != nil)
493 5cdb1798 2005-10-29 devnull if(last->fileno > highest)
494 5cdb1798 2005-10-29 devnull highest = last->fileno;
495 5cdb1798 2005-10-29 devnull
496 7e61af51 2006-02-12 devnull n = fsdirreadall(fd, &d);
497 5cdb1798 2005-10-29 devnull for(i = 0; i < n; i++){
498 5cdb1798 2005-10-29 devnull if((d[i].qid.type & QTDIR) == 0)
499 5cdb1798 2005-10-29 devnull continue;
500 5cdb1798 2005-10-29 devnull if(atoi(d[i].name) <= highest)
501 5cdb1798 2005-10-29 devnull continue;
502 5cdb1798 2005-10-29 devnull m = file2message(parent, d[i].name);
503 cbeb0b26 2006-04-01 devnull /* fprint(2,"returned from file2message\n"); */
504 5cdb1798 2005-10-29 devnull if(m == nil)
505 5cdb1798 2005-10-29 devnull break;
506 5cdb1798 2005-10-29 devnull newmsgs++;
507 5cdb1798 2005-10-29 devnull if(reverse){
508 5cdb1798 2005-10-29 devnull m->next = first;
509 5cdb1798 2005-10-29 devnull if(first != nil)
510 5cdb1798 2005-10-29 devnull first->prev = m;
511 5cdb1798 2005-10-29 devnull first = m;
512 5cdb1798 2005-10-29 devnull } else {
513 5cdb1798 2005-10-29 devnull if(first == nil)
514 5cdb1798 2005-10-29 devnull first = m;
515 5cdb1798 2005-10-29 devnull else
516 5cdb1798 2005-10-29 devnull last->next = m;
517 5cdb1798 2005-10-29 devnull m->prev = last;
518 5cdb1798 2005-10-29 devnull last = m;
519 5cdb1798 2005-10-29 devnull }
520 7e61af51 2006-02-12 devnull }
521 5cdb1798 2005-10-29 devnull free(d);
522 7e61af51 2006-02-12 devnull fsclose(fd);
523 5cdb1798 2005-10-29 devnull parent->child = first;
524 5cdb1798 2005-10-29 devnull
525 cbeb0b26 2006-04-01 devnull /* renumber and file longest from */
526 5cdb1798 2005-10-29 devnull i = 1;
527 5cdb1798 2005-10-29 devnull longestfrom = 12;
528 5cdb1798 2005-10-29 devnull for(m = first; m != nil; m = m->next){
529 5cdb1798 2005-10-29 devnull m->id = natural ? m->fileno : i++;
530 5cdb1798 2005-10-29 devnull n = strlen(m->from);
531 5cdb1798 2005-10-29 devnull if(n > longestfrom)
532 5cdb1798 2005-10-29 devnull longestfrom = n;
533 5cdb1798 2005-10-29 devnull }
534 5cdb1798 2005-10-29 devnull
535 5cdb1798 2005-10-29 devnull return newmsgs;
536 5cdb1798 2005-10-29 devnull }
537 5cdb1798 2005-10-29 devnull
538 cbeb0b26 2006-04-01 devnull /* */
539 cbeb0b26 2006-04-01 devnull /* point directly to a message */
540 cbeb0b26 2006-04-01 devnull /* */
541 5cdb1798 2005-10-29 devnull Message*
542 5cdb1798 2005-10-29 devnull dosingleton(Message *parent, char *path)
543 5cdb1798 2005-10-29 devnull {
544 5cdb1798 2005-10-29 devnull char *p, *np;
545 5cdb1798 2005-10-29 devnull Message *m;
546 5cdb1798 2005-10-29 devnull
547 cbeb0b26 2006-04-01 devnull /* walk down to message and read it */
548 5cdb1798 2005-10-29 devnull if(strlen(path) < rootlen)
549 5cdb1798 2005-10-29 devnull return nil;
550 5cdb1798 2005-10-29 devnull if(path[rootlen] != '/')
551 5cdb1798 2005-10-29 devnull return nil;
552 5cdb1798 2005-10-29 devnull p = path+rootlen+1;
553 5cdb1798 2005-10-29 devnull np = strchr(p, '/');
554 5cdb1798 2005-10-29 devnull if(np != nil)
555 5cdb1798 2005-10-29 devnull *np = 0;
556 5cdb1798 2005-10-29 devnull m = file2message(parent, p);
557 5cdb1798 2005-10-29 devnull if(m == nil)
558 5cdb1798 2005-10-29 devnull return nil;
559 5cdb1798 2005-10-29 devnull parent->child = m;
560 5cdb1798 2005-10-29 devnull m->id = 1;
561 5cdb1798 2005-10-29 devnull
562 cbeb0b26 2006-04-01 devnull /* walk down to requested component */
563 5cdb1798 2005-10-29 devnull while(np != nil){
564 5cdb1798 2005-10-29 devnull *np = '/';
565 5cdb1798 2005-10-29 devnull np = strchr(np+1, '/');
566 5cdb1798 2005-10-29 devnull if(np != nil)
567 5cdb1798 2005-10-29 devnull *np = 0;
568 5cdb1798 2005-10-29 devnull for(m = m->child; m != nil; m = m->next)
569 5cdb1798 2005-10-29 devnull if(strcmp(path, s_to_c(m->path)) == 0)
570 5cdb1798 2005-10-29 devnull return m;
571 5cdb1798 2005-10-29 devnull if(m == nil)
572 5cdb1798 2005-10-29 devnull return nil;
573 5cdb1798 2005-10-29 devnull }
574 5cdb1798 2005-10-29 devnull return m;
575 5cdb1798 2005-10-29 devnull }
576 5cdb1798 2005-10-29 devnull
577 cbeb0b26 2006-04-01 devnull /* */
578 cbeb0b26 2006-04-01 devnull /* read a file into a string */
579 cbeb0b26 2006-04-01 devnull /* */
580 5cdb1798 2005-10-29 devnull String*
581 5cdb1798 2005-10-29 devnull file2string(String *dir, char *file)
582 5cdb1798 2005-10-29 devnull {
583 5cdb1798 2005-10-29 devnull String *s;
584 5cdb1798 2005-10-29 devnull int n, m;
585 7e61af51 2006-02-12 devnull CFid *fd;
586 5cdb1798 2005-10-29 devnull
587 5cdb1798 2005-10-29 devnull s = extendpath(dir, file);
588 7e61af51 2006-02-12 devnull fd = fsopen(mailfs, s_to_c(s), OREAD);
589 5cdb1798 2005-10-29 devnull s_grow(s, 512); /* avoid multiple reads on info files */
590 5cdb1798 2005-10-29 devnull s_reset(s);
591 7e61af51 2006-02-12 devnull if(fd == nil)
592 5cdb1798 2005-10-29 devnull return s;
593 5cdb1798 2005-10-29 devnull
594 5cdb1798 2005-10-29 devnull for(;;){
595 5cdb1798 2005-10-29 devnull n = s->end - s->ptr;
596 5cdb1798 2005-10-29 devnull if(n == 0){
597 5cdb1798 2005-10-29 devnull s_grow(s, 128);
598 5cdb1798 2005-10-29 devnull continue;
599 5cdb1798 2005-10-29 devnull }
600 7e61af51 2006-02-12 devnull m = fsread(fd, s->ptr, n);
601 5cdb1798 2005-10-29 devnull if(m <= 0)
602 5cdb1798 2005-10-29 devnull break;
603 5cdb1798 2005-10-29 devnull s->ptr += m;
604 5cdb1798 2005-10-29 devnull if(m < n)
605 5cdb1798 2005-10-29 devnull break;
606 5cdb1798 2005-10-29 devnull }
607 5cdb1798 2005-10-29 devnull s_terminate(s);
608 7e61af51 2006-02-12 devnull fsclose(fd);
609 5cdb1798 2005-10-29 devnull
610 5cdb1798 2005-10-29 devnull return s;
611 5cdb1798 2005-10-29 devnull }
612 5cdb1798 2005-10-29 devnull
613 cbeb0b26 2006-04-01 devnull /* */
614 cbeb0b26 2006-04-01 devnull /* get the length of a file */
615 cbeb0b26 2006-04-01 devnull /* */
616 5cdb1798 2005-10-29 devnull int
617 5cdb1798 2005-10-29 devnull filelen(String *dir, char *file)
618 5cdb1798 2005-10-29 devnull {
619 5cdb1798 2005-10-29 devnull String *path;
620 5cdb1798 2005-10-29 devnull Dir *d;
621 5cdb1798 2005-10-29 devnull int rv;
622 5cdb1798 2005-10-29 devnull
623 5cdb1798 2005-10-29 devnull path = extendpath(dir, file);
624 7e61af51 2006-02-12 devnull d = fsdirstat(mailfs, s_to_c(path));
625 5cdb1798 2005-10-29 devnull if(d == nil){
626 5cdb1798 2005-10-29 devnull s_free(path);
627 5cdb1798 2005-10-29 devnull return -1;
628 5cdb1798 2005-10-29 devnull }
629 5cdb1798 2005-10-29 devnull s_free(path);
630 5cdb1798 2005-10-29 devnull rv = d->length;
631 5cdb1798 2005-10-29 devnull free(d);
632 5cdb1798 2005-10-29 devnull return rv;
633 5cdb1798 2005-10-29 devnull }
634 5cdb1798 2005-10-29 devnull
635 cbeb0b26 2006-04-01 devnull /* */
636 cbeb0b26 2006-04-01 devnull /* walk the path name an element */
637 cbeb0b26 2006-04-01 devnull /* */
638 5cdb1798 2005-10-29 devnull String*
639 5cdb1798 2005-10-29 devnull extendpath(String *dir, char *name)
640 5cdb1798 2005-10-29 devnull {
641 5cdb1798 2005-10-29 devnull String *path;
642 5cdb1798 2005-10-29 devnull
643 5cdb1798 2005-10-29 devnull if(strcmp(s_to_c(dir), ".") == 0)
644 5cdb1798 2005-10-29 devnull path = s_new();
645 5cdb1798 2005-10-29 devnull else {
646 5cdb1798 2005-10-29 devnull path = s_copy(s_to_c(dir));
647 5cdb1798 2005-10-29 devnull s_append(path, "/");
648 5cdb1798 2005-10-29 devnull }
649 5cdb1798 2005-10-29 devnull s_append(path, name);
650 5cdb1798 2005-10-29 devnull return path;
651 5cdb1798 2005-10-29 devnull }
652 5cdb1798 2005-10-29 devnull
653 5cdb1798 2005-10-29 devnull int
654 5cdb1798 2005-10-29 devnull cistrncmp(char *a, char *b, int n)
655 5cdb1798 2005-10-29 devnull {
656 5cdb1798 2005-10-29 devnull while(n-- > 0){
657 5cdb1798 2005-10-29 devnull if(tolower(*a++) != tolower(*b++))
658 5cdb1798 2005-10-29 devnull return -1;
659 5cdb1798 2005-10-29 devnull }
660 5cdb1798 2005-10-29 devnull return 0;
661 5cdb1798 2005-10-29 devnull }
662 5cdb1798 2005-10-29 devnull
663 5cdb1798 2005-10-29 devnull int
664 5cdb1798 2005-10-29 devnull cistrcmp(char *a, char *b)
665 5cdb1798 2005-10-29 devnull {
666 5cdb1798 2005-10-29 devnull for(;;){
667 5cdb1798 2005-10-29 devnull if(tolower(*a) != tolower(*b++))
668 5cdb1798 2005-10-29 devnull return -1;
669 5cdb1798 2005-10-29 devnull if(*a++ == 0)
670 5cdb1798 2005-10-29 devnull break;
671 5cdb1798 2005-10-29 devnull }
672 5cdb1798 2005-10-29 devnull return 0;
673 5cdb1798 2005-10-29 devnull }
674 5cdb1798 2005-10-29 devnull
675 5cdb1798 2005-10-29 devnull char*
676 5cdb1798 2005-10-29 devnull nosecs(char *t)
677 5cdb1798 2005-10-29 devnull {
678 5cdb1798 2005-10-29 devnull char *p;
679 5cdb1798 2005-10-29 devnull
680 5cdb1798 2005-10-29 devnull p = strchr(t, ':');
681 5cdb1798 2005-10-29 devnull if(p == nil)
682 5cdb1798 2005-10-29 devnull return t;
683 5cdb1798 2005-10-29 devnull p = strchr(p+1, ':');
684 5cdb1798 2005-10-29 devnull if(p != nil)
685 5cdb1798 2005-10-29 devnull *p = 0;
686 5cdb1798 2005-10-29 devnull return t;
687 5cdb1798 2005-10-29 devnull }
688 5cdb1798 2005-10-29 devnull
689 5cdb1798 2005-10-29 devnull char *months[12] =
690 5cdb1798 2005-10-29 devnull {
691 5cdb1798 2005-10-29 devnull "jan", "feb", "mar", "apr", "may", "jun",
692 5cdb1798 2005-10-29 devnull "jul", "aug", "sep", "oct", "nov", "dec"
693 5cdb1798 2005-10-29 devnull };
694 5cdb1798 2005-10-29 devnull
695 5cdb1798 2005-10-29 devnull int
696 5cdb1798 2005-10-29 devnull month(char *m)
697 5cdb1798 2005-10-29 devnull {
698 5cdb1798 2005-10-29 devnull int i;
699 5cdb1798 2005-10-29 devnull
700 5cdb1798 2005-10-29 devnull for(i = 0; i < 12; i++)
701 5cdb1798 2005-10-29 devnull if(cistrcmp(m, months[i]) == 0)
702 5cdb1798 2005-10-29 devnull return i+1;
703 5cdb1798 2005-10-29 devnull return 1;
704 5cdb1798 2005-10-29 devnull }
705 5cdb1798 2005-10-29 devnull
706 5cdb1798 2005-10-29 devnull enum
707 5cdb1798 2005-10-29 devnull {
708 5cdb1798 2005-10-29 devnull Yearsecs= 365*24*60*60
709 5cdb1798 2005-10-29 devnull };
710 5cdb1798 2005-10-29 devnull
711 5cdb1798 2005-10-29 devnull void
712 5cdb1798 2005-10-29 devnull cracktime(char *d, char *out, int len)
713 5cdb1798 2005-10-29 devnull {
714 5cdb1798 2005-10-29 devnull char in[64];
715 5cdb1798 2005-10-29 devnull char *f[6];
716 5cdb1798 2005-10-29 devnull int n;
717 5cdb1798 2005-10-29 devnull Tm tm;
718 5cdb1798 2005-10-29 devnull long now, then;
719 5cdb1798 2005-10-29 devnull char *dtime;
720 5cdb1798 2005-10-29 devnull
721 5cdb1798 2005-10-29 devnull *out = 0;
722 5cdb1798 2005-10-29 devnull if(d == nil)
723 5cdb1798 2005-10-29 devnull return;
724 5cdb1798 2005-10-29 devnull strncpy(in, d, sizeof(in));
725 5cdb1798 2005-10-29 devnull in[sizeof(in)-1] = 0;
726 5cdb1798 2005-10-29 devnull n = getfields(in, f, 6, 1, " \t\r\n");
727 5cdb1798 2005-10-29 devnull if(n != 6){
728 cbeb0b26 2006-04-01 devnull /* unknown style */
729 5cdb1798 2005-10-29 devnull snprint(out, 16, "%10.10s", d);
730 5cdb1798 2005-10-29 devnull return;
731 5cdb1798 2005-10-29 devnull }
732 5cdb1798 2005-10-29 devnull now = time(0);
733 5cdb1798 2005-10-29 devnull memset(&tm, 0, sizeof tm);
734 5cdb1798 2005-10-29 devnull if(strchr(f[0], ',') != nil && strchr(f[4], ':') != nil){
735 cbeb0b26 2006-04-01 devnull /* 822 style */
736 5cdb1798 2005-10-29 devnull tm.year = atoi(f[3])-1900;
737 5cdb1798 2005-10-29 devnull tm.mon = month(f[2]);
738 5cdb1798 2005-10-29 devnull tm.mday = atoi(f[1]);
739 5cdb1798 2005-10-29 devnull dtime = nosecs(f[4]);
740 5cdb1798 2005-10-29 devnull then = tm2sec(&tm);
741 5cdb1798 2005-10-29 devnull } else if(strchr(f[3], ':') != nil){
742 cbeb0b26 2006-04-01 devnull /* unix style */
743 5cdb1798 2005-10-29 devnull tm.year = atoi(f[5])-1900;
744 5cdb1798 2005-10-29 devnull tm.mon = month(f[1]);
745 5cdb1798 2005-10-29 devnull tm.mday = atoi(f[2]);
746 5cdb1798 2005-10-29 devnull dtime = nosecs(f[3]);
747 5cdb1798 2005-10-29 devnull then = tm2sec(&tm);
748 5cdb1798 2005-10-29 devnull } else {
749 5cdb1798 2005-10-29 devnull then = now;
750 5cdb1798 2005-10-29 devnull tm = *localtime(now);
751 5cdb1798 2005-10-29 devnull dtime = "";
752 5cdb1798 2005-10-29 devnull }
753 5cdb1798 2005-10-29 devnull
754 5cdb1798 2005-10-29 devnull if(now - then < Yearsecs/2)
755 5cdb1798 2005-10-29 devnull snprint(out, len, "%2d/%2.2d %s", tm.mon, tm.mday, dtime);
756 5cdb1798 2005-10-29 devnull else
757 5cdb1798 2005-10-29 devnull snprint(out, len, "%2d/%2.2d %4d", tm.mon, tm.mday, tm.year+1900);
758 5cdb1798 2005-10-29 devnull }
759 5cdb1798 2005-10-29 devnull
760 5cdb1798 2005-10-29 devnull Ctype*
761 5cdb1798 2005-10-29 devnull findctype(Message *m)
762 5cdb1798 2005-10-29 devnull {
763 5cdb1798 2005-10-29 devnull char *p;
764 5cdb1798 2005-10-29 devnull char ftype[128];
765 5cdb1798 2005-10-29 devnull int n, pfd[2];
766 5cdb1798 2005-10-29 devnull Ctype *a, *cp;
767 5cdb1798 2005-10-29 devnull static Ctype bintype = { "application/octet-stream", "bin", 0, 0 };
768 5cdb1798 2005-10-29 devnull
769 5cdb1798 2005-10-29 devnull for(cp = ctype; cp; cp = cp->next)
770 5cdb1798 2005-10-29 devnull if(strncmp(cp->type, m->type, strlen(cp->type)) == 0)
771 5cdb1798 2005-10-29 devnull return cp;
772 5cdb1798 2005-10-29 devnull
773 5cdb1798 2005-10-29 devnull if(pipe(pfd) < 0)
774 5cdb1798 2005-10-29 devnull return &bintype;
775 5cdb1798 2005-10-29 devnull
776 5cdb1798 2005-10-29 devnull *ftype = 0;
777 5cdb1798 2005-10-29 devnull switch(fork()){
778 5cdb1798 2005-10-29 devnull case -1:
779 5cdb1798 2005-10-29 devnull break;
780 5cdb1798 2005-10-29 devnull case 0:
781 5cdb1798 2005-10-29 devnull close(pfd[1]);
782 5cdb1798 2005-10-29 devnull close(0);
783 5cdb1798 2005-10-29 devnull dup(pfd[0], 0);
784 5cdb1798 2005-10-29 devnull close(1);
785 5cdb1798 2005-10-29 devnull dup(pfd[0], 1);
786 5cdb1798 2005-10-29 devnull execl(unsharp("#9/bin/file"), "file", "-m", s_to_c(extendpath(m->path, "body")), nil);
787 5cdb1798 2005-10-29 devnull threadexits(0);
788 5cdb1798 2005-10-29 devnull default:
789 5cdb1798 2005-10-29 devnull close(pfd[0]);
790 5cdb1798 2005-10-29 devnull n = read(pfd[1], ftype, sizeof(ftype));
791 5cdb1798 2005-10-29 devnull if(n > 0)
792 5cdb1798 2005-10-29 devnull ftype[n] = 0;
793 5cdb1798 2005-10-29 devnull close(pfd[1]);
794 5cdb1798 2005-10-29 devnull waitpid();
795 5cdb1798 2005-10-29 devnull break;
796 5cdb1798 2005-10-29 devnull }
797 5cdb1798 2005-10-29 devnull
798 5cdb1798 2005-10-29 devnull if (*ftype=='\0' || (p = strchr(ftype, '/')) == nil)
799 5cdb1798 2005-10-29 devnull return &bintype;
800 5cdb1798 2005-10-29 devnull *p++ = 0;
801 5cdb1798 2005-10-29 devnull
802 5cdb1798 2005-10-29 devnull a = mallocz(sizeof(Ctype), 1);
803 5cdb1798 2005-10-29 devnull a->type = strdup(ftype);
804 5cdb1798 2005-10-29 devnull a->ext = strdup(p);
805 5cdb1798 2005-10-29 devnull a->display = 0;
806 5cdb1798 2005-10-29 devnull a->plumbdest = strdup(ftype);
807 5cdb1798 2005-10-29 devnull for(cp = ctype; cp->next; cp = cp->next)
808 5cdb1798 2005-10-29 devnull continue;
809 5cdb1798 2005-10-29 devnull cp->next = a;
810 5cdb1798 2005-10-29 devnull a->next = nil;
811 5cdb1798 2005-10-29 devnull return a;
812 5cdb1798 2005-10-29 devnull }
813 5cdb1798 2005-10-29 devnull
814 5cdb1798 2005-10-29 devnull void
815 5cdb1798 2005-10-29 devnull mkid(String *s, Message *m)
816 5cdb1798 2005-10-29 devnull {
817 5cdb1798 2005-10-29 devnull char buf[32];
818 5cdb1798 2005-10-29 devnull
819 5cdb1798 2005-10-29 devnull if(m->parent != &top){
820 5cdb1798 2005-10-29 devnull mkid(s, m->parent);
821 5cdb1798 2005-10-29 devnull s_append(s, ".");
822 5cdb1798 2005-10-29 devnull }
823 5cdb1798 2005-10-29 devnull sprint(buf, "%d", m->id);
824 5cdb1798 2005-10-29 devnull s_append(s, buf);
825 5cdb1798 2005-10-29 devnull }
826 5cdb1798 2005-10-29 devnull
827 5cdb1798 2005-10-29 devnull void
828 5cdb1798 2005-10-29 devnull snprintheader(char *buf, int len, Message *m)
829 5cdb1798 2005-10-29 devnull {
830 5cdb1798 2005-10-29 devnull char timebuf[32];
831 5cdb1798 2005-10-29 devnull String *id;
832 5cdb1798 2005-10-29 devnull char *p, *q;;
833 5cdb1798 2005-10-29 devnull
834 cbeb0b26 2006-04-01 devnull /* create id */
835 5cdb1798 2005-10-29 devnull id = s_new();
836 5cdb1798 2005-10-29 devnull mkid(id, m);
837 5cdb1798 2005-10-29 devnull
838 5cdb1798 2005-10-29 devnull if(*m->from == 0){
839 cbeb0b26 2006-04-01 devnull /* no from */
840 5cdb1798 2005-10-29 devnull snprint(buf, len, "%-3s %s %6d %s",
841 5cdb1798 2005-10-29 devnull s_to_c(id),
842 5cdb1798 2005-10-29 devnull m->type,
843 5cdb1798 2005-10-29 devnull m->len,
844 5cdb1798 2005-10-29 devnull m->filename);
845 5cdb1798 2005-10-29 devnull } else if(*m->subject){
846 5cdb1798 2005-10-29 devnull q = p = strdup(m->subject);
847 5cdb1798 2005-10-29 devnull while(*p == ' ')
848 5cdb1798 2005-10-29 devnull p++;
849 5cdb1798 2005-10-29 devnull if(strlen(p) > 50)
850 5cdb1798 2005-10-29 devnull p[50] = 0;
851 5cdb1798 2005-10-29 devnull cracktime(m->date, timebuf, sizeof(timebuf));
852 5cdb1798 2005-10-29 devnull snprint(buf, len, "%-3s %c%c%c %6d %11.11s %-*.*s %s",
853 5cdb1798 2005-10-29 devnull s_to_c(id),
854 5cdb1798 2005-10-29 devnull m->child ? 'H' : ' ',
855 5cdb1798 2005-10-29 devnull m->deleted ? 'd' : ' ',
856 5cdb1798 2005-10-29 devnull m->stored ? 's' : ' ',
857 5cdb1798 2005-10-29 devnull m->len,
858 5cdb1798 2005-10-29 devnull timebuf,
859 5cdb1798 2005-10-29 devnull longestfrom, longestfrom, m->from,
860 5cdb1798 2005-10-29 devnull p);
861 5cdb1798 2005-10-29 devnull free(q);
862 5cdb1798 2005-10-29 devnull } else {
863 5cdb1798 2005-10-29 devnull cracktime(m->date, timebuf, sizeof(timebuf));
864 5cdb1798 2005-10-29 devnull snprint(buf, len, "%-3s %c%c%c %6d %11.11s %s",
865 5cdb1798 2005-10-29 devnull s_to_c(id),
866 5cdb1798 2005-10-29 devnull m->child ? 'H' : ' ',
867 5cdb1798 2005-10-29 devnull m->deleted ? 'd' : ' ',
868 5cdb1798 2005-10-29 devnull m->stored ? 's' : ' ',
869 5cdb1798 2005-10-29 devnull m->len,
870 5cdb1798 2005-10-29 devnull timebuf,
871 5cdb1798 2005-10-29 devnull m->from);
872 5cdb1798 2005-10-29 devnull }
873 5cdb1798 2005-10-29 devnull s_free(id);
874 5cdb1798 2005-10-29 devnull }
875 5cdb1798 2005-10-29 devnull
876 5cdb1798 2005-10-29 devnull char *spaces = " ";
877 5cdb1798 2005-10-29 devnull
878 5cdb1798 2005-10-29 devnull void
879 5cdb1798 2005-10-29 devnull snprintHeader(char *buf, int len, int indent, Message *m)
880 5cdb1798 2005-10-29 devnull {
881 5cdb1798 2005-10-29 devnull String *id;
882 5cdb1798 2005-10-29 devnull char typeid[64];
883 5cdb1798 2005-10-29 devnull char *p, *e;
884 5cdb1798 2005-10-29 devnull
885 cbeb0b26 2006-04-01 devnull /* create id */
886 5cdb1798 2005-10-29 devnull id = s_new();
887 5cdb1798 2005-10-29 devnull mkid(id, m);
888 5cdb1798 2005-10-29 devnull
889 5cdb1798 2005-10-29 devnull e = buf + len;
890 5cdb1798 2005-10-29 devnull
891 5cdb1798 2005-10-29 devnull snprint(typeid, sizeof typeid, "%s %s", s_to_c(id), m->type);
892 5cdb1798 2005-10-29 devnull if(indent < 6)
893 5cdb1798 2005-10-29 devnull p = seprint(buf, e, "%-32s %-6d ", typeid, m->len);
894 5cdb1798 2005-10-29 devnull else
895 5cdb1798 2005-10-29 devnull p = seprint(buf, e, "%-64s %-6d ", typeid, m->len);
896 5cdb1798 2005-10-29 devnull if(m->filename && *m->filename)
897 5cdb1798 2005-10-29 devnull p = seprint(p, e, "(file,%s)", m->filename);
898 5cdb1798 2005-10-29 devnull if(m->from && *m->from)
899 5cdb1798 2005-10-29 devnull p = seprint(p, e, "(from,%s)", m->from);
900 5cdb1798 2005-10-29 devnull if(m->subject && *m->subject)
901 5cdb1798 2005-10-29 devnull seprint(p, e, "(subj,%s)", m->subject);
902 5cdb1798 2005-10-29 devnull
903 5cdb1798 2005-10-29 devnull s_free(id);
904 5cdb1798 2005-10-29 devnull }
905 5cdb1798 2005-10-29 devnull
906 5cdb1798 2005-10-29 devnull char sstring[256];
907 5cdb1798 2005-10-29 devnull
908 cbeb0b26 2006-04-01 devnull /* cmd := range cmd ' ' arg-list ; */
909 cbeb0b26 2006-04-01 devnull /* range := address */
910 cbeb0b26 2006-04-01 devnull /* | address ',' address */
911 cbeb0b26 2006-04-01 devnull /* | 'g' search ; */
912 cbeb0b26 2006-04-01 devnull /* address := msgno */
913 cbeb0b26 2006-04-01 devnull /* | search ; */
914 cbeb0b26 2006-04-01 devnull /* msgno := number */
915 cbeb0b26 2006-04-01 devnull /* | number '/' msgno ; */
916 cbeb0b26 2006-04-01 devnull /* search := '/' string '/' */
917 cbeb0b26 2006-04-01 devnull /* | '%' string '%' ; */
918 cbeb0b26 2006-04-01 devnull /* */
919 5cdb1798 2005-10-29 devnull Reprog*
920 5cdb1798 2005-10-29 devnull parsesearch(char **pp)
921 5cdb1798 2005-10-29 devnull {
922 5cdb1798 2005-10-29 devnull char *p, *np;
923 5cdb1798 2005-10-29 devnull int c, n;
924 5cdb1798 2005-10-29 devnull
925 5cdb1798 2005-10-29 devnull p = *pp;
926 5cdb1798 2005-10-29 devnull c = *p++;
927 5cdb1798 2005-10-29 devnull np = strchr(p, c);
928 5cdb1798 2005-10-29 devnull if(np != nil){
929 5cdb1798 2005-10-29 devnull *np++ = 0;
930 5cdb1798 2005-10-29 devnull *pp = np;
931 5cdb1798 2005-10-29 devnull } else {
932 5cdb1798 2005-10-29 devnull n = strlen(p);
933 5cdb1798 2005-10-29 devnull *pp = p + n;
934 5cdb1798 2005-10-29 devnull }
935 5cdb1798 2005-10-29 devnull if(*p == 0)
936 5cdb1798 2005-10-29 devnull p = sstring;
937 5cdb1798 2005-10-29 devnull else{
938 5cdb1798 2005-10-29 devnull strncpy(sstring, p, sizeof(sstring));
939 5cdb1798 2005-10-29 devnull sstring[sizeof(sstring)-1] = 0;
940 5cdb1798 2005-10-29 devnull }
941 5cdb1798 2005-10-29 devnull return regcomp(p);
942 5cdb1798 2005-10-29 devnull }
943 5cdb1798 2005-10-29 devnull
944 5cdb1798 2005-10-29 devnull char*
945 5cdb1798 2005-10-29 devnull parseaddr(char **pp, Message *first, Message *cur, Message *unspec, Message **mp)
946 5cdb1798 2005-10-29 devnull {
947 5cdb1798 2005-10-29 devnull int n;
948 5cdb1798 2005-10-29 devnull Message *m;
949 5cdb1798 2005-10-29 devnull char *p;
950 5cdb1798 2005-10-29 devnull Reprog *prog;
951 5cdb1798 2005-10-29 devnull int c, sign;
952 5cdb1798 2005-10-29 devnull char buf[256];
953 5cdb1798 2005-10-29 devnull
954 5cdb1798 2005-10-29 devnull *mp = nil;
955 5cdb1798 2005-10-29 devnull p = *pp;
956 5cdb1798 2005-10-29 devnull
957 5cdb1798 2005-10-29 devnull if(*p == '+'){
958 5cdb1798 2005-10-29 devnull sign = 1;
959 5cdb1798 2005-10-29 devnull p++;
960 5cdb1798 2005-10-29 devnull *pp = p;
961 5cdb1798 2005-10-29 devnull } else if(*p == '-'){
962 5cdb1798 2005-10-29 devnull sign = -1;
963 5cdb1798 2005-10-29 devnull p++;
964 5cdb1798 2005-10-29 devnull *pp = p;
965 5cdb1798 2005-10-29 devnull } else
966 5cdb1798 2005-10-29 devnull sign = 0;
967 5cdb1798 2005-10-29 devnull
968 5cdb1798 2005-10-29 devnull switch(*p){
969 5cdb1798 2005-10-29 devnull default:
970 5cdb1798 2005-10-29 devnull if(sign){
971 5cdb1798 2005-10-29 devnull n = 1;
972 5cdb1798 2005-10-29 devnull goto number;
973 5cdb1798 2005-10-29 devnull }
974 5cdb1798 2005-10-29 devnull *mp = unspec;
975 5cdb1798 2005-10-29 devnull break;
976 5cdb1798 2005-10-29 devnull case '0': case '1': case '2': case '3': case '4':
977 5cdb1798 2005-10-29 devnull case '5': case '6': case '7': case '8': case '9':
978 5cdb1798 2005-10-29 devnull n = strtoul(p, pp, 10);
979 5cdb1798 2005-10-29 devnull if(n == 0){
980 5cdb1798 2005-10-29 devnull if(sign)
981 5cdb1798 2005-10-29 devnull *mp = cur;
982 5cdb1798 2005-10-29 devnull else
983 5cdb1798 2005-10-29 devnull *mp = &top;
984 5cdb1798 2005-10-29 devnull break;
985 5cdb1798 2005-10-29 devnull }
986 5cdb1798 2005-10-29 devnull number:
987 5cdb1798 2005-10-29 devnull m = nil;
988 5cdb1798 2005-10-29 devnull switch(sign){
989 5cdb1798 2005-10-29 devnull case 0:
990 5cdb1798 2005-10-29 devnull for(m = first; m != nil; m = m->next)
991 5cdb1798 2005-10-29 devnull if(m->id == n)
992 5cdb1798 2005-10-29 devnull break;
993 5cdb1798 2005-10-29 devnull break;
994 5cdb1798 2005-10-29 devnull case -1:
995 5cdb1798 2005-10-29 devnull if(cur != &top)
996 5cdb1798 2005-10-29 devnull for(m = cur; m != nil && n > 0; n--)
997 5cdb1798 2005-10-29 devnull m = m->prev;
998 5cdb1798 2005-10-29 devnull break;
999 5cdb1798 2005-10-29 devnull case 1:
1000 5cdb1798 2005-10-29 devnull if(cur == &top){
1001 5cdb1798 2005-10-29 devnull n--;
1002 5cdb1798 2005-10-29 devnull cur = first;
1003 5cdb1798 2005-10-29 devnull }
1004 5cdb1798 2005-10-29 devnull for(m = cur; m != nil && n > 0; n--)
1005 5cdb1798 2005-10-29 devnull m = m->next;
1006 5cdb1798 2005-10-29 devnull break;
1007 5cdb1798 2005-10-29 devnull }
1008 5cdb1798 2005-10-29 devnull if(m == nil)
1009 5cdb1798 2005-10-29 devnull return "address";
1010 5cdb1798 2005-10-29 devnull *mp = m;
1011 5cdb1798 2005-10-29 devnull break;
1012 5cdb1798 2005-10-29 devnull case '%':
1013 5cdb1798 2005-10-29 devnull case '/':
1014 5cdb1798 2005-10-29 devnull case '?':
1015 5cdb1798 2005-10-29 devnull c = *p;
1016 5cdb1798 2005-10-29 devnull prog = parsesearch(pp);
1017 5cdb1798 2005-10-29 devnull if(prog == nil)
1018 5cdb1798 2005-10-29 devnull return "badly formed regular expression";
1019 5cdb1798 2005-10-29 devnull m = nil;
1020 5cdb1798 2005-10-29 devnull switch(c){
1021 5cdb1798 2005-10-29 devnull case '%':
1022 5cdb1798 2005-10-29 devnull for(m = cur == &top ? first : cur->next; m != nil; m = m->next){
1023 5cdb1798 2005-10-29 devnull if(rawsearch(m, prog))
1024 5cdb1798 2005-10-29 devnull break;
1025 5cdb1798 2005-10-29 devnull }
1026 5cdb1798 2005-10-29 devnull break;
1027 5cdb1798 2005-10-29 devnull case '/':
1028 5cdb1798 2005-10-29 devnull for(m = cur == &top ? first : cur->next; m != nil; m = m->next){
1029 5cdb1798 2005-10-29 devnull snprintheader(buf, sizeof(buf), m);
1030 5cdb1798 2005-10-29 devnull if(regexec(prog, buf, nil, 0))
1031 5cdb1798 2005-10-29 devnull break;
1032 5cdb1798 2005-10-29 devnull }
1033 5cdb1798 2005-10-29 devnull break;
1034 5cdb1798 2005-10-29 devnull case '?':
1035 5cdb1798 2005-10-29 devnull for(m = cur == &top ? nil : cur->prev; m != nil; m = m->prev){
1036 5cdb1798 2005-10-29 devnull snprintheader(buf, sizeof(buf), m);
1037 5cdb1798 2005-10-29 devnull if(regexec(prog, buf, nil, 0))
1038 5cdb1798 2005-10-29 devnull break;
1039 5cdb1798 2005-10-29 devnull }
1040 5cdb1798 2005-10-29 devnull break;
1041 5cdb1798 2005-10-29 devnull }
1042 5cdb1798 2005-10-29 devnull if(m == nil)
1043 5cdb1798 2005-10-29 devnull return "search";
1044 5cdb1798 2005-10-29 devnull *mp = m;
1045 5cdb1798 2005-10-29 devnull free(prog);
1046 5cdb1798 2005-10-29 devnull break;
1047 5cdb1798 2005-10-29 devnull case '$':
1048 5cdb1798 2005-10-29 devnull for(m = first; m != nil && m->next != nil; m = m->next)
1049 5cdb1798 2005-10-29 devnull ;
1050 5cdb1798 2005-10-29 devnull *mp = m;
1051 5cdb1798 2005-10-29 devnull *pp = p+1;
1052 5cdb1798 2005-10-29 devnull break;
1053 5cdb1798 2005-10-29 devnull case '.':
1054 5cdb1798 2005-10-29 devnull *mp = cur;
1055 5cdb1798 2005-10-29 devnull *pp = p+1;
1056 5cdb1798 2005-10-29 devnull break;
1057 5cdb1798 2005-10-29 devnull case ',':
1058 5cdb1798 2005-10-29 devnull *mp = first;
1059 5cdb1798 2005-10-29 devnull *pp = p;
1060 5cdb1798 2005-10-29 devnull break;
1061 5cdb1798 2005-10-29 devnull }
1062 5cdb1798 2005-10-29 devnull
1063 5cdb1798 2005-10-29 devnull if(*mp != nil && **pp == '.'){
1064 5cdb1798 2005-10-29 devnull (*pp)++;
1065 5cdb1798 2005-10-29 devnull if((*mp)->child == nil)
1066 5cdb1798 2005-10-29 devnull return "no sub parts";
1067 5cdb1798 2005-10-29 devnull return parseaddr(pp, (*mp)->child, (*mp)->child, (*mp)->child, mp);
1068 5cdb1798 2005-10-29 devnull }
1069 5cdb1798 2005-10-29 devnull if(**pp == '+' || **pp == '-' || **pp == '/' || **pp == '%')
1070 5cdb1798 2005-10-29 devnull return parseaddr(pp, first, *mp, *mp, mp);
1071 5cdb1798 2005-10-29 devnull
1072 5cdb1798 2005-10-29 devnull return nil;
1073 5cdb1798 2005-10-29 devnull }
1074 5cdb1798 2005-10-29 devnull
1075 cbeb0b26 2006-04-01 devnull /* */
1076 cbeb0b26 2006-04-01 devnull /* search a message for a regular expression match */
1077 cbeb0b26 2006-04-01 devnull /* */
1078 5cdb1798 2005-10-29 devnull int
1079 5cdb1798 2005-10-29 devnull rawsearch(Message *m, Reprog *prog)
1080 5cdb1798 2005-10-29 devnull {
1081 5cdb1798 2005-10-29 devnull char buf[4096+1];
1082 5cdb1798 2005-10-29 devnull int i, rv;
1083 7e61af51 2006-02-12 devnull CFid *fd;
1084 5cdb1798 2005-10-29 devnull String *path;
1085 5cdb1798 2005-10-29 devnull
1086 5cdb1798 2005-10-29 devnull path = extendpath(m->path, "raw");
1087 7e61af51 2006-02-12 devnull fd = fsopen(mailfs, s_to_c(path), OREAD);
1088 7e61af51 2006-02-12 devnull if(fd == nil)
1089 5cdb1798 2005-10-29 devnull return 0;
1090 5cdb1798 2005-10-29 devnull
1091 cbeb0b26 2006-04-01 devnull /* march through raw message 4096 bytes at a time */
1092 cbeb0b26 2006-04-01 devnull /* with a 128 byte overlap to chain the re search. */
1093 5cdb1798 2005-10-29 devnull rv = 0;
1094 5cdb1798 2005-10-29 devnull for(;;){
1095 7e61af51 2006-02-12 devnull i = fsread(fd, buf, sizeof(buf)-1);
1096 5cdb1798 2005-10-29 devnull if(i <= 0)
1097 5cdb1798 2005-10-29 devnull break;
1098 5cdb1798 2005-10-29 devnull buf[i] = 0;
1099 5cdb1798 2005-10-29 devnull if(regexec(prog, buf, nil, 0)){
1100 5cdb1798 2005-10-29 devnull rv = 1;
1101 5cdb1798 2005-10-29 devnull break;
1102 5cdb1798 2005-10-29 devnull }
1103 5cdb1798 2005-10-29 devnull if(i < sizeof(buf)-1)
1104 5cdb1798 2005-10-29 devnull break;
1105 7e61af51 2006-02-12 devnull if(fsseek(fd, -128LL, 1) < 0)
1106 5cdb1798 2005-10-29 devnull break;
1107 5cdb1798 2005-10-29 devnull }
1108 5cdb1798 2005-10-29 devnull
1109 7e61af51 2006-02-12 devnull fsclose(fd);
1110 5cdb1798 2005-10-29 devnull s_free(path);
1111 5cdb1798 2005-10-29 devnull return rv;
1112 5cdb1798 2005-10-29 devnull }
1113 5cdb1798 2005-10-29 devnull
1114 5cdb1798 2005-10-29 devnull
1115 5cdb1798 2005-10-29 devnull char*
1116 5cdb1798 2005-10-29 devnull parsecmd(char *p, Cmd *cmd, Message *first, Message *cur)
1117 5cdb1798 2005-10-29 devnull {
1118 5cdb1798 2005-10-29 devnull Reprog *prog;
1119 5cdb1798 2005-10-29 devnull Message *m, *s, *e, **l, *last;
1120 5cdb1798 2005-10-29 devnull char buf[256];
1121 5cdb1798 2005-10-29 devnull char *err;
1122 5cdb1798 2005-10-29 devnull int i, c;
1123 5cdb1798 2005-10-29 devnull char *q;
1124 5cdb1798 2005-10-29 devnull static char errbuf[Errlen];
1125 5cdb1798 2005-10-29 devnull
1126 5cdb1798 2005-10-29 devnull cmd->delete = 0;
1127 5cdb1798 2005-10-29 devnull l = &cmd->msgs;
1128 5cdb1798 2005-10-29 devnull *l = nil;
1129 5cdb1798 2005-10-29 devnull
1130 cbeb0b26 2006-04-01 devnull /* eat white space */
1131 5cdb1798 2005-10-29 devnull while(*p == ' ')
1132 5cdb1798 2005-10-29 devnull p++;
1133 5cdb1798 2005-10-29 devnull
1134 cbeb0b26 2006-04-01 devnull /* null command is a special case (advance and print) */
1135 5cdb1798 2005-10-29 devnull if(*p == 0){
1136 5cdb1798 2005-10-29 devnull if(cur == &top){
1137 cbeb0b26 2006-04-01 devnull /* special case */
1138 5cdb1798 2005-10-29 devnull m = first;
1139 5cdb1798 2005-10-29 devnull } else {
1140 cbeb0b26 2006-04-01 devnull /* walk to the next message even if we have to go up */
1141 5cdb1798 2005-10-29 devnull m = cur->next;
1142 5cdb1798 2005-10-29 devnull while(m == nil && cur->parent != nil){
1143 5cdb1798 2005-10-29 devnull cur = cur->parent;
1144 5cdb1798 2005-10-29 devnull m = cur->next;
1145 5cdb1798 2005-10-29 devnull }
1146 5cdb1798 2005-10-29 devnull }
1147 5cdb1798 2005-10-29 devnull if(m == nil)
1148 5cdb1798 2005-10-29 devnull return "address";
1149 5cdb1798 2005-10-29 devnull *l = m;
1150 5cdb1798 2005-10-29 devnull m->cmd = nil;
1151 5cdb1798 2005-10-29 devnull cmd->an = 0;
1152 5cdb1798 2005-10-29 devnull cmd->f = pcmd;
1153 5cdb1798 2005-10-29 devnull return nil;
1154 5cdb1798 2005-10-29 devnull }
1155 5cdb1798 2005-10-29 devnull
1156 cbeb0b26 2006-04-01 devnull /* global search ? */
1157 5cdb1798 2005-10-29 devnull if(*p == 'g'){
1158 5cdb1798 2005-10-29 devnull p++;
1159 5cdb1798 2005-10-29 devnull
1160 cbeb0b26 2006-04-01 devnull /* no search string means all messages */
1161 5cdb1798 2005-10-29 devnull if(*p != '/' && *p != '%'){
1162 5cdb1798 2005-10-29 devnull for(m = first; m != nil; m = m->next){
1163 5cdb1798 2005-10-29 devnull *l = m;
1164 5cdb1798 2005-10-29 devnull l = &m->cmd;
1165 5cdb1798 2005-10-29 devnull *l = nil;
1166 5cdb1798 2005-10-29 devnull }
1167 5cdb1798 2005-10-29 devnull } else {
1168 cbeb0b26 2006-04-01 devnull /* mark all messages matching this search string */
1169 5cdb1798 2005-10-29 devnull c = *p;
1170 5cdb1798 2005-10-29 devnull prog = parsesearch(&p);
1171 5cdb1798 2005-10-29 devnull if(prog == nil)
1172 5cdb1798 2005-10-29 devnull return "badly formed regular expression";
1173 5cdb1798 2005-10-29 devnull if(c == '%'){
1174 5cdb1798 2005-10-29 devnull for(m = first; m != nil; m = m->next){
1175 5cdb1798 2005-10-29 devnull if(rawsearch(m, prog)){
1176 5cdb1798 2005-10-29 devnull *l = m;
1177 5cdb1798 2005-10-29 devnull l = &m->cmd;
1178 5cdb1798 2005-10-29 devnull *l = nil;
1179 5cdb1798 2005-10-29 devnull }
1180 5cdb1798 2005-10-29 devnull }
1181 5cdb1798 2005-10-29 devnull } else {
1182 5cdb1798 2005-10-29 devnull for(m = first; m != nil; m = m->next){
1183 5cdb1798 2005-10-29 devnull snprintheader(buf, sizeof(buf), m);
1184 5cdb1798 2005-10-29 devnull if(regexec(prog, buf, nil, 0)){
1185 5cdb1798 2005-10-29 devnull *l = m;
1186 5cdb1798 2005-10-29 devnull l = &m->cmd;
1187 5cdb1798 2005-10-29 devnull *l = nil;
1188 5cdb1798 2005-10-29 devnull }
1189 5cdb1798 2005-10-29 devnull }
1190 5cdb1798 2005-10-29 devnull }
1191 5cdb1798 2005-10-29 devnull free(prog);
1192 5cdb1798 2005-10-29 devnull }
1193 5cdb1798 2005-10-29 devnull } else {
1194 5cdb1798 2005-10-29 devnull
1195 cbeb0b26 2006-04-01 devnull /* parse an address */
1196 5cdb1798 2005-10-29 devnull s = e = nil;
1197 5cdb1798 2005-10-29 devnull err = parseaddr(&p, first, cur, cur, &s);
1198 5cdb1798 2005-10-29 devnull if(err != nil)
1199 5cdb1798 2005-10-29 devnull return err;
1200 5cdb1798 2005-10-29 devnull if(*p == ','){
1201 cbeb0b26 2006-04-01 devnull /* this is an address range */
1202 5cdb1798 2005-10-29 devnull if(s == &top)
1203 5cdb1798 2005-10-29 devnull s = first;
1204 5cdb1798 2005-10-29 devnull p++;
1205 5cdb1798 2005-10-29 devnull for(last = s; last != nil && last->next != nil; last = last->next)
1206 5cdb1798 2005-10-29 devnull ;
1207 5cdb1798 2005-10-29 devnull err = parseaddr(&p, first, cur, last, &e);
1208 5cdb1798 2005-10-29 devnull if(err != nil)
1209 5cdb1798 2005-10-29 devnull return err;
1210 5cdb1798 2005-10-29 devnull
1211 cbeb0b26 2006-04-01 devnull /* select all messages in the range */
1212 5cdb1798 2005-10-29 devnull for(; s != nil; s = s->next){
1213 5cdb1798 2005-10-29 devnull *l = s;
1214 5cdb1798 2005-10-29 devnull l = &s->cmd;
1215 5cdb1798 2005-10-29 devnull *l = nil;
1216 5cdb1798 2005-10-29 devnull if(s == e)
1217 5cdb1798 2005-10-29 devnull break;
1218 5cdb1798 2005-10-29 devnull }
1219 5cdb1798 2005-10-29 devnull if(s == nil)
1220 5cdb1798 2005-10-29 devnull return "null address range";
1221 5cdb1798 2005-10-29 devnull } else {
1222 cbeb0b26 2006-04-01 devnull /* single address */
1223 5cdb1798 2005-10-29 devnull if(s != &top){
1224 5cdb1798 2005-10-29 devnull *l = s;
1225 5cdb1798 2005-10-29 devnull s->cmd = nil;
1226 5cdb1798 2005-10-29 devnull }
1227 5cdb1798 2005-10-29 devnull }
1228 5cdb1798 2005-10-29 devnull }
1229 5cdb1798 2005-10-29 devnull
1230 cbeb0b26 2006-04-01 devnull /* insert a space after '!'s and '|'s */
1231 5cdb1798 2005-10-29 devnull for(q = p; *q; q++)
1232 5cdb1798 2005-10-29 devnull if(*q != '!' && *q != '|')
1233 5cdb1798 2005-10-29 devnull break;
1234 5cdb1798 2005-10-29 devnull if(q != p && *q != ' '){
1235 5cdb1798 2005-10-29 devnull memmove(q+1, q, strlen(q)+1);
1236 5cdb1798 2005-10-29 devnull *q = ' ';
1237 5cdb1798 2005-10-29 devnull }
1238 5cdb1798 2005-10-29 devnull
1239 5cdb1798 2005-10-29 devnull cmd->an = getfields(p, cmd->av, nelem(cmd->av) - 1, 1, " \t\r\n");
1240 5cdb1798 2005-10-29 devnull if(cmd->an == 0 || *cmd->av[0] == 0)
1241 5cdb1798 2005-10-29 devnull cmd->f = pcmd;
1242 5cdb1798 2005-10-29 devnull else {
1243 cbeb0b26 2006-04-01 devnull /* hack to allow all messages to start with 'd' */
1244 5cdb1798 2005-10-29 devnull if(*(cmd->av[0]) == 'd' && *(cmd->av[0]+1) != 0){
1245 5cdb1798 2005-10-29 devnull cmd->delete = 1;
1246 5cdb1798 2005-10-29 devnull cmd->av[0]++;
1247 5cdb1798 2005-10-29 devnull }
1248 5cdb1798 2005-10-29 devnull
1249 cbeb0b26 2006-04-01 devnull /* search command table */
1250 5cdb1798 2005-10-29 devnull for(i = 0; cmdtab[i].cmd != nil; i++)
1251 5cdb1798 2005-10-29 devnull if(strcmp(cmd->av[0], cmdtab[i].cmd) == 0)
1252 5cdb1798 2005-10-29 devnull break;
1253 5cdb1798 2005-10-29 devnull if(cmdtab[i].cmd == nil)
1254 5cdb1798 2005-10-29 devnull return "illegal command";
1255 5cdb1798 2005-10-29 devnull if(cmdtab[i].args == 0 && cmd->an > 1){
1256 5cdb1798 2005-10-29 devnull snprint(errbuf, sizeof(errbuf), "%s doesn't take an argument", cmdtab[i].cmd);
1257 5cdb1798 2005-10-29 devnull return errbuf;
1258 5cdb1798 2005-10-29 devnull }
1259 5cdb1798 2005-10-29 devnull cmd->f = cmdtab[i].f;
1260 5cdb1798 2005-10-29 devnull }
1261 5cdb1798 2005-10-29 devnull return nil;
1262 5cdb1798 2005-10-29 devnull }
1263 5cdb1798 2005-10-29 devnull
1264 cbeb0b26 2006-04-01 devnull /* inefficient read from standard input */
1265 5cdb1798 2005-10-29 devnull char*
1266 5cdb1798 2005-10-29 devnull readline(char *prompt, char *line, int len)
1267 5cdb1798 2005-10-29 devnull {
1268 5cdb1798 2005-10-29 devnull char *p, *e;
1269 5cdb1798 2005-10-29 devnull int n;
1270 5cdb1798 2005-10-29 devnull
1271 5cdb1798 2005-10-29 devnull retry:
1272 5cdb1798 2005-10-29 devnull interrupted = 0;
1273 5cdb1798 2005-10-29 devnull Bprint(&out, "%s", prompt);
1274 5cdb1798 2005-10-29 devnull Bflush(&out);
1275 5cdb1798 2005-10-29 devnull e = line + len;
1276 5cdb1798 2005-10-29 devnull for(p = line; p < e; p++){
1277 5cdb1798 2005-10-29 devnull n = read(0, p, 1);
1278 5cdb1798 2005-10-29 devnull if(n < 0){
1279 5cdb1798 2005-10-29 devnull if(interrupted)
1280 5cdb1798 2005-10-29 devnull goto retry;
1281 5cdb1798 2005-10-29 devnull return nil;
1282 5cdb1798 2005-10-29 devnull }
1283 5cdb1798 2005-10-29 devnull if(n == 0)
1284 5cdb1798 2005-10-29 devnull return nil;
1285 5cdb1798 2005-10-29 devnull if(*p == '\n')
1286 5cdb1798 2005-10-29 devnull break;
1287 5cdb1798 2005-10-29 devnull }
1288 5cdb1798 2005-10-29 devnull *p = 0;
1289 5cdb1798 2005-10-29 devnull return line;
1290 5cdb1798 2005-10-29 devnull }
1291 5cdb1798 2005-10-29 devnull
1292 5cdb1798 2005-10-29 devnull void
1293 5cdb1798 2005-10-29 devnull messagecount(Message *m)
1294 5cdb1798 2005-10-29 devnull {
1295 5cdb1798 2005-10-29 devnull int i;
1296 5cdb1798 2005-10-29 devnull
1297 5cdb1798 2005-10-29 devnull i = 0;
1298 5cdb1798 2005-10-29 devnull for(; m != nil; m = m->next)
1299 5cdb1798 2005-10-29 devnull i++;
1300 5cdb1798 2005-10-29 devnull Bprint(&out, "%d message%s\n", i, plural(i));
1301 5cdb1798 2005-10-29 devnull }
1302 5cdb1798 2005-10-29 devnull
1303 5cdb1798 2005-10-29 devnull Message*
1304 5cdb1798 2005-10-29 devnull aichcmd(Message *m, int indent)
1305 5cdb1798 2005-10-29 devnull {
1306 5cdb1798 2005-10-29 devnull char hdr[256];
1307 5cdb1798 2005-10-29 devnull
1308 5cdb1798 2005-10-29 devnull if(m == &top)
1309 5cdb1798 2005-10-29 devnull return nil;
1310 5cdb1798 2005-10-29 devnull
1311 5cdb1798 2005-10-29 devnull snprintHeader(hdr, sizeof(hdr), indent, m);
1312 5cdb1798 2005-10-29 devnull Bprint(&out, "%s\n", hdr);
1313 5cdb1798 2005-10-29 devnull for(m = m->child; m != nil; m = m->next)
1314 5cdb1798 2005-10-29 devnull aichcmd(m, indent+1);
1315 5cdb1798 2005-10-29 devnull return nil;
1316 5cdb1798 2005-10-29 devnull }
1317 5cdb1798 2005-10-29 devnull
1318 5cdb1798 2005-10-29 devnull Message*
1319 7e61af51 2006-02-12 devnull Hcmd(Cmd *x, Message *m)
1320 5cdb1798 2005-10-29 devnull {
1321 7e61af51 2006-02-12 devnull USED(x);
1322 7e61af51 2006-02-12 devnull
1323 5cdb1798 2005-10-29 devnull if(m == &top)
1324 5cdb1798 2005-10-29 devnull return nil;
1325 5cdb1798 2005-10-29 devnull aichcmd(m, 0);
1326 5cdb1798 2005-10-29 devnull return nil;
1327 5cdb1798 2005-10-29 devnull }
1328 5cdb1798 2005-10-29 devnull
1329 5cdb1798 2005-10-29 devnull Message*
1330 7e61af51 2006-02-12 devnull hcmd(Cmd *x, Message *m)
1331 5cdb1798 2005-10-29 devnull {
1332 5cdb1798 2005-10-29 devnull char hdr[256];
1333 5cdb1798 2005-10-29 devnull
1334 7e61af51 2006-02-12 devnull USED(x);
1335 5cdb1798 2005-10-29 devnull if(m == &top)
1336 5cdb1798 2005-10-29 devnull return nil;
1337 5cdb1798 2005-10-29 devnull
1338 5cdb1798 2005-10-29 devnull snprintheader(hdr, sizeof(hdr), m);
1339 5cdb1798 2005-10-29 devnull Bprint(&out, "%s\n", hdr);
1340 5cdb1798 2005-10-29 devnull return nil;
1341 5cdb1798 2005-10-29 devnull }
1342 5cdb1798 2005-10-29 devnull
1343 5cdb1798 2005-10-29 devnull Message*
1344 7e61af51 2006-02-12 devnull bcmd(Cmd *x, Message *m)
1345 5cdb1798 2005-10-29 devnull {
1346 5cdb1798 2005-10-29 devnull int i;
1347 5cdb1798 2005-10-29 devnull Message *om = m;
1348 5cdb1798 2005-10-29 devnull
1349 7e61af51 2006-02-12 devnull USED(x);
1350 5cdb1798 2005-10-29 devnull if(m == &top)
1351 5cdb1798 2005-10-29 devnull m = top.child;
1352 5cdb1798 2005-10-29 devnull for(i = 0; i < 10 && m != nil; i++){
1353 5cdb1798 2005-10-29 devnull hcmd(nil, m);
1354 5cdb1798 2005-10-29 devnull om = m;
1355 5cdb1798 2005-10-29 devnull m = m->next;
1356 5cdb1798 2005-10-29 devnull }
1357 5cdb1798 2005-10-29 devnull
1358 5cdb1798 2005-10-29 devnull return om;
1359 5cdb1798 2005-10-29 devnull }
1360 5cdb1798 2005-10-29 devnull
1361 5cdb1798 2005-10-29 devnull Message*
1362 7e61af51 2006-02-12 devnull ncmd(Cmd *x, Message *m)
1363 5cdb1798 2005-10-29 devnull {
1364 7e61af51 2006-02-12 devnull USED(x);
1365 5cdb1798 2005-10-29 devnull if(m == &top)
1366 5cdb1798 2005-10-29 devnull return m->child;
1367 5cdb1798 2005-10-29 devnull return m->next;
1368 5cdb1798 2005-10-29 devnull }
1369 5cdb1798 2005-10-29 devnull
1370 5cdb1798 2005-10-29 devnull int
1371 5cdb1798 2005-10-29 devnull printpart(String *s, char *part)
1372 5cdb1798 2005-10-29 devnull {
1373 5cdb1798 2005-10-29 devnull char buf[4096];
1374 5cdb1798 2005-10-29 devnull int n, tot;
1375 7e61af51 2006-02-12 devnull CFid *fd;
1376 5cdb1798 2005-10-29 devnull String *path;
1377 5cdb1798 2005-10-29 devnull
1378 5cdb1798 2005-10-29 devnull path = extendpath(s, part);
1379 7e61af51 2006-02-12 devnull fd = fsopen(mailfs, s_to_c(path), OREAD);
1380 5cdb1798 2005-10-29 devnull s_free(path);
1381 7e61af51 2006-02-12 devnull if(fd == nil){
1382 5cdb1798 2005-10-29 devnull fprint(2, "!message dissappeared\n");
1383 5cdb1798 2005-10-29 devnull return 0;
1384 5cdb1798 2005-10-29 devnull }
1385 5cdb1798 2005-10-29 devnull tot = 0;
1386 7e61af51 2006-02-12 devnull while((n = fsread(fd, buf, sizeof(buf))) > 0){
1387 5cdb1798 2005-10-29 devnull if(interrupted)
1388 5cdb1798 2005-10-29 devnull break;
1389 5cdb1798 2005-10-29 devnull if(Bwrite(&out, buf, n) <= 0)
1390 5cdb1798 2005-10-29 devnull break;
1391 5cdb1798 2005-10-29 devnull tot += n;
1392 5cdb1798 2005-10-29 devnull }
1393 7e61af51 2006-02-12 devnull fsclose(fd);
1394 5cdb1798 2005-10-29 devnull return tot;
1395 5cdb1798 2005-10-29 devnull }
1396 5cdb1798 2005-10-29 devnull
1397 5cdb1798 2005-10-29 devnull int
1398 5cdb1798 2005-10-29 devnull printhtml(Message *m)
1399 5cdb1798 2005-10-29 devnull {
1400 5cdb1798 2005-10-29 devnull Cmd c;
1401 5cdb1798 2005-10-29 devnull
1402 5cdb1798 2005-10-29 devnull c.an = 3;
1403 7e61af51 2006-02-12 devnull c.av[1] = "htmlfmt";
1404 5cdb1798 2005-10-29 devnull c.av[2] = "-l 40 -cutf-8";
1405 5cdb1798 2005-10-29 devnull Bprint(&out, "!%s\n", c.av[1]);
1406 5cdb1798 2005-10-29 devnull Bflush(&out);
1407 5cdb1798 2005-10-29 devnull pipecmd(&c, m);
1408 5cdb1798 2005-10-29 devnull return 0;
1409 5cdb1798 2005-10-29 devnull }
1410 5cdb1798 2005-10-29 devnull
1411 5cdb1798 2005-10-29 devnull Message*
1412 7e61af51 2006-02-12 devnull Pcmd(Cmd *x, Message *m)
1413 5cdb1798 2005-10-29 devnull {
1414 7e61af51 2006-02-12 devnull USED(x);
1415 5cdb1798 2005-10-29 devnull if(m == &top)
1416 5cdb1798 2005-10-29 devnull return &top;
1417 5cdb1798 2005-10-29 devnull if(m->parent == &top)
1418 5cdb1798 2005-10-29 devnull printpart(m->path, "unixheader");
1419 5cdb1798 2005-10-29 devnull printpart(m->path, "raw");
1420 5cdb1798 2005-10-29 devnull return m;
1421 5cdb1798 2005-10-29 devnull }
1422 5cdb1798 2005-10-29 devnull
1423 5cdb1798 2005-10-29 devnull void
1424 5cdb1798 2005-10-29 devnull compress(char *p)
1425 5cdb1798 2005-10-29 devnull {
1426 5cdb1798 2005-10-29 devnull char *np;
1427 5cdb1798 2005-10-29 devnull int last;
1428 5cdb1798 2005-10-29 devnull
1429 5cdb1798 2005-10-29 devnull last = ' ';
1430 5cdb1798 2005-10-29 devnull for(np = p; *p; p++){
1431 5cdb1798 2005-10-29 devnull if(*p != ' ' || last != ' '){
1432 5cdb1798 2005-10-29 devnull last = *p;
1433 5cdb1798 2005-10-29 devnull *np++ = last;
1434 5cdb1798 2005-10-29 devnull }
1435 5cdb1798 2005-10-29 devnull }
1436 5cdb1798 2005-10-29 devnull *np = 0;
1437 5cdb1798 2005-10-29 devnull }
1438 5cdb1798 2005-10-29 devnull
1439 5cdb1798 2005-10-29 devnull Message*
1440 7e61af51 2006-02-12 devnull pcmd(Cmd *x, Message *m)
1441 5cdb1798 2005-10-29 devnull {
1442 5cdb1798 2005-10-29 devnull Message *nm;
1443 5cdb1798 2005-10-29 devnull Ctype *cp;
1444 5cdb1798 2005-10-29 devnull String *s;
1445 5cdb1798 2005-10-29 devnull char buf[128];
1446 5cdb1798 2005-10-29 devnull
1447 7e61af51 2006-02-12 devnull USED(x);
1448 5cdb1798 2005-10-29 devnull if(m == &top)
1449 5cdb1798 2005-10-29 devnull return &top;
1450 5cdb1798 2005-10-29 devnull if(m->parent == &top)
1451 5cdb1798 2005-10-29 devnull printpart(m->path, "unixheader");
1452 5cdb1798 2005-10-29 devnull if(printpart(m->path, "header") > 0)
1453 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
1454 5cdb1798 2005-10-29 devnull cp = findctype(m);
1455 5cdb1798 2005-10-29 devnull if(cp->display){
1456 5cdb1798 2005-10-29 devnull if(strcmp(m->type, "text/html") == 0)
1457 5cdb1798 2005-10-29 devnull printhtml(m);
1458 5cdb1798 2005-10-29 devnull else
1459 5cdb1798 2005-10-29 devnull printpart(m->path, "body");
1460 5cdb1798 2005-10-29 devnull } else if(strcmp(m->type, "multipart/alternative") == 0){
1461 5cdb1798 2005-10-29 devnull for(nm = m->child; nm != nil; nm = nm->next){
1462 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1463 5cdb1798 2005-10-29 devnull if(cp->ext != nil && strncmp(cp->ext, "txt", 3) == 0)
1464 5cdb1798 2005-10-29 devnull break;
1465 5cdb1798 2005-10-29 devnull }
1466 5cdb1798 2005-10-29 devnull if(nm == nil)
1467 5cdb1798 2005-10-29 devnull for(nm = m->child; nm != nil; nm = nm->next){
1468 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1469 5cdb1798 2005-10-29 devnull if(cp->display)
1470 5cdb1798 2005-10-29 devnull break;
1471 5cdb1798 2005-10-29 devnull }
1472 5cdb1798 2005-10-29 devnull if(nm != nil)
1473 5cdb1798 2005-10-29 devnull pcmd(nil, nm);
1474 5cdb1798 2005-10-29 devnull else
1475 5cdb1798 2005-10-29 devnull hcmd(nil, m);
1476 5cdb1798 2005-10-29 devnull } else if(strncmp(m->type, "multipart/", 10) == 0){
1477 5cdb1798 2005-10-29 devnull nm = m->child;
1478 5cdb1798 2005-10-29 devnull if(nm != nil){
1479 cbeb0b26 2006-04-01 devnull /* always print first part */
1480 5cdb1798 2005-10-29 devnull pcmd(nil, nm);
1481 5cdb1798 2005-10-29 devnull
1482 5cdb1798 2005-10-29 devnull for(nm = nm->next; nm != nil; nm = nm->next){
1483 5cdb1798 2005-10-29 devnull s = rooted(s_clone(nm->path));
1484 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1485 5cdb1798 2005-10-29 devnull snprintHeader(buf, sizeof buf, -1, nm);
1486 5cdb1798 2005-10-29 devnull compress(buf);
1487 5cdb1798 2005-10-29 devnull if(strcmp(nm->disposition, "inline") == 0){
1488 5cdb1798 2005-10-29 devnull if(cp->ext != nil)
1489 5cdb1798 2005-10-29 devnull Bprint(&out, "\n--- %s %s/body.%s\n\n",
1490 5cdb1798 2005-10-29 devnull buf, s_to_c(s), cp->ext);
1491 5cdb1798 2005-10-29 devnull else
1492 5cdb1798 2005-10-29 devnull Bprint(&out, "\n--- %s %s/body\n\n",
1493 5cdb1798 2005-10-29 devnull buf, s_to_c(s));
1494 5cdb1798 2005-10-29 devnull pcmd(nil, nm);
1495 5cdb1798 2005-10-29 devnull } else {
1496 5cdb1798 2005-10-29 devnull if(cp->ext != nil)
1497 5cdb1798 2005-10-29 devnull Bprint(&out, "\n!--- %s %s/body.%s\n",
1498 5cdb1798 2005-10-29 devnull buf, s_to_c(s), cp->ext);
1499 5cdb1798 2005-10-29 devnull else
1500 5cdb1798 2005-10-29 devnull Bprint(&out, "\n!--- %s %s/body\n",
1501 5cdb1798 2005-10-29 devnull buf, s_to_c(s));
1502 5cdb1798 2005-10-29 devnull }
1503 5cdb1798 2005-10-29 devnull s_free(s);
1504 5cdb1798 2005-10-29 devnull }
1505 5cdb1798 2005-10-29 devnull } else {
1506 5cdb1798 2005-10-29 devnull hcmd(nil, m);
1507 5cdb1798 2005-10-29 devnull }
1508 5cdb1798 2005-10-29 devnull } else if(strcmp(m->type, "message/rfc822") == 0){
1509 5cdb1798 2005-10-29 devnull pcmd(nil, m->child);
1510 5cdb1798 2005-10-29 devnull } else if(plumb(m, cp) >= 0)
1511 5cdb1798 2005-10-29 devnull Bprint(&out, "\n!--- using plumber to display message of type %s\n", m->type);
1512 5cdb1798 2005-10-29 devnull else
1513 5cdb1798 2005-10-29 devnull Bprint(&out, "\n!--- cannot display messages of type %s\n", m->type);
1514 5cdb1798 2005-10-29 devnull
1515 5cdb1798 2005-10-29 devnull return m;
1516 5cdb1798 2005-10-29 devnull }
1517 5cdb1798 2005-10-29 devnull
1518 5cdb1798 2005-10-29 devnull void
1519 5cdb1798 2005-10-29 devnull printpartindented(String *s, char *part, char *indent)
1520 5cdb1798 2005-10-29 devnull {
1521 d4baecd9 2006-02-26 devnull int fd;
1522 5cdb1798 2005-10-29 devnull char *p;
1523 5cdb1798 2005-10-29 devnull String *path;
1524 5cdb1798 2005-10-29 devnull Biobuf *b;
1525 5cdb1798 2005-10-29 devnull
1526 d4baecd9 2006-02-26 devnull path = extendpath(s, part);
1527 d4baecd9 2006-02-26 devnull fd = fsopenfd(mailfs, s_to_c(path), OREAD);
1528 5cdb1798 2005-10-29 devnull s_free(path);
1529 d4baecd9 2006-02-26 devnull if(fd < 0){
1530 d4baecd9 2006-02-26 devnull fprint(2, "!message disappeared\n");
1531 d4baecd9 2006-02-26 devnull return;
1532 d4baecd9 2006-02-26 devnull }
1533 d4baecd9 2006-02-26 devnull b = Bfdopen(fd, OREAD);
1534 d4baecd9 2006-02-26 devnull if(b == 0){
1535 d4baecd9 2006-02-26 devnull fprint(2, "out of memory\n");
1536 d4baecd9 2006-02-26 devnull close(fd);
1537 5cdb1798 2005-10-29 devnull return;
1538 5cdb1798 2005-10-29 devnull }
1539 5cdb1798 2005-10-29 devnull while((p = Brdline(b, '\n')) != nil){
1540 5cdb1798 2005-10-29 devnull if(interrupted)
1541 5cdb1798 2005-10-29 devnull break;
1542 5cdb1798 2005-10-29 devnull p[Blinelen(b)-1] = 0;
1543 ee51985f 2006-01-27 devnull if(Bprint(&out, "%s%s\n", indent, p) < 0)
1544 5cdb1798 2005-10-29 devnull break;
1545 5cdb1798 2005-10-29 devnull }
1546 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
1547 5cdb1798 2005-10-29 devnull Bterm(b);
1548 5cdb1798 2005-10-29 devnull }
1549 5cdb1798 2005-10-29 devnull
1550 5cdb1798 2005-10-29 devnull Message*
1551 7e61af51 2006-02-12 devnull quotecmd(Cmd *x, Message *m)
1552 5cdb1798 2005-10-29 devnull {
1553 5cdb1798 2005-10-29 devnull Message *nm;
1554 5cdb1798 2005-10-29 devnull Ctype *cp;
1555 5cdb1798 2005-10-29 devnull
1556 7e61af51 2006-02-12 devnull USED(x);
1557 5cdb1798 2005-10-29 devnull if(m == &top)
1558 5cdb1798 2005-10-29 devnull return &top;
1559 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
1560 5cdb1798 2005-10-29 devnull if(m->from != nil && *m->from)
1561 5cdb1798 2005-10-29 devnull Bprint(&out, "On %s, %s wrote:\n", m->date, m->from);
1562 5cdb1798 2005-10-29 devnull cp = findctype(m);
1563 5cdb1798 2005-10-29 devnull if(cp->display){
1564 5cdb1798 2005-10-29 devnull printpartindented(m->path, "body", "> ");
1565 5cdb1798 2005-10-29 devnull } else if(strcmp(m->type, "multipart/alternative") == 0){
1566 5cdb1798 2005-10-29 devnull for(nm = m->child; nm != nil; nm = nm->next){
1567 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1568 5cdb1798 2005-10-29 devnull if(cp->ext != nil && strncmp(cp->ext, "txt", 3) == 0)
1569 5cdb1798 2005-10-29 devnull break;
1570 5cdb1798 2005-10-29 devnull }
1571 5cdb1798 2005-10-29 devnull if(nm == nil)
1572 5cdb1798 2005-10-29 devnull for(nm = m->child; nm != nil; nm = nm->next){
1573 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1574 5cdb1798 2005-10-29 devnull if(cp->display)
1575 5cdb1798 2005-10-29 devnull break;
1576 5cdb1798 2005-10-29 devnull }
1577 5cdb1798 2005-10-29 devnull if(nm != nil)
1578 5cdb1798 2005-10-29 devnull quotecmd(nil, nm);
1579 5cdb1798 2005-10-29 devnull } else if(strncmp(m->type, "multipart/", 10) == 0){
1580 5cdb1798 2005-10-29 devnull nm = m->child;
1581 5cdb1798 2005-10-29 devnull if(nm != nil){
1582 5cdb1798 2005-10-29 devnull cp = findctype(nm);
1583 5cdb1798 2005-10-29 devnull if(cp->display || strncmp(m->type, "multipart/", 10) == 0)
1584 5cdb1798 2005-10-29 devnull quotecmd(nil, nm);
1585 5cdb1798 2005-10-29 devnull }
1586 5cdb1798 2005-10-29 devnull }
1587 5cdb1798 2005-10-29 devnull return m;
1588 5cdb1798 2005-10-29 devnull }
1589 5cdb1798 2005-10-29 devnull
1590 cbeb0b26 2006-04-01 devnull /* really delete messages */
1591 5cdb1798 2005-10-29 devnull Message*
1592 5cdb1798 2005-10-29 devnull flushdeleted(Message *cur)
1593 5cdb1798 2005-10-29 devnull {
1594 5cdb1798 2005-10-29 devnull Message *m, **l;
1595 5cdb1798 2005-10-29 devnull char buf[1024], *p, *e, *msg;
1596 5cdb1798 2005-10-29 devnull int deld, n;
1597 7e61af51 2006-02-12 devnull CFid *fd;
1598 5cdb1798 2005-10-29 devnull int i;
1599 5cdb1798 2005-10-29 devnull
1600 5cdb1798 2005-10-29 devnull doflush = 0;
1601 5cdb1798 2005-10-29 devnull deld = 0;
1602 5cdb1798 2005-10-29 devnull
1603 1ea614ff 2006-02-15 devnull snprint(buf, sizeof buf, "%s/ctl", mbname);
1604 1ea614ff 2006-02-15 devnull fd = fsopen(mailfs, buf, OWRITE);
1605 7e61af51 2006-02-12 devnull if(fd == nil){
1606 1ea614ff 2006-02-15 devnull fprint(2, "!can't delete mail, opening %s: %r\n", buf);
1607 5cdb1798 2005-10-29 devnull exitfs(0);
1608 5cdb1798 2005-10-29 devnull }
1609 5cdb1798 2005-10-29 devnull e = &buf[sizeof(buf)];
1610 1ea614ff 2006-02-15 devnull p = seprint(buf, e, "delete");
1611 5cdb1798 2005-10-29 devnull n = 0;
1612 5cdb1798 2005-10-29 devnull for(l = &top.child; *l != nil;){
1613 5cdb1798 2005-10-29 devnull m = *l;
1614 5cdb1798 2005-10-29 devnull if(!m->deleted){
1615 5cdb1798 2005-10-29 devnull l = &(*l)->next;
1616 5cdb1798 2005-10-29 devnull continue;
1617 5cdb1798 2005-10-29 devnull }
1618 5cdb1798 2005-10-29 devnull
1619 cbeb0b26 2006-04-01 devnull /* don't return a pointer to a deleted message */
1620 5cdb1798 2005-10-29 devnull if(m == cur)
1621 5cdb1798 2005-10-29 devnull cur = m->next;
1622 5cdb1798 2005-10-29 devnull
1623 5cdb1798 2005-10-29 devnull deld++;
1624 5cdb1798 2005-10-29 devnull msg = strrchr(s_to_c(m->path), '/');
1625 5cdb1798 2005-10-29 devnull if(msg == nil)
1626 5cdb1798 2005-10-29 devnull msg = s_to_c(m->path);
1627 5cdb1798 2005-10-29 devnull else
1628 5cdb1798 2005-10-29 devnull msg++;
1629 5cdb1798 2005-10-29 devnull if(e-p < 10){
1630 7e61af51 2006-02-12 devnull fswrite(fd, buf, p-buf);
1631 5cdb1798 2005-10-29 devnull n = 0;
1632 1ea614ff 2006-02-15 devnull p = seprint(buf, e, "delete");
1633 5cdb1798 2005-10-29 devnull }
1634 5cdb1798 2005-10-29 devnull p = seprint(p, e, " %s", msg);
1635 5cdb1798 2005-10-29 devnull n++;
1636 5cdb1798 2005-10-29 devnull
1637 cbeb0b26 2006-04-01 devnull /* unchain and free */
1638 5cdb1798 2005-10-29 devnull *l = m->next;
1639 5cdb1798 2005-10-29 devnull if(m->next)
1640 5cdb1798 2005-10-29 devnull m->next->prev = m->prev;
1641 5cdb1798 2005-10-29 devnull freemessage(m);
1642 5cdb1798 2005-10-29 devnull }
1643 5cdb1798 2005-10-29 devnull if(n)
1644 7e61af51 2006-02-12 devnull fswrite(fd, buf, p-buf);
1645 5cdb1798 2005-10-29 devnull
1646 7e61af51 2006-02-12 devnull fsclose(fd);
1647 5cdb1798 2005-10-29 devnull
1648 5cdb1798 2005-10-29 devnull if(deld)
1649 5cdb1798 2005-10-29 devnull Bprint(&out, "!%d message%s deleted\n", deld, plural(deld));
1650 5cdb1798 2005-10-29 devnull
1651 cbeb0b26 2006-04-01 devnull /* renumber */
1652 5cdb1798 2005-10-29 devnull i = 1;
1653 5cdb1798 2005-10-29 devnull for(m = top.child; m != nil; m = m->next)
1654 5cdb1798 2005-10-29 devnull m->id = natural ? m->fileno : i++;
1655 5cdb1798 2005-10-29 devnull
1656 cbeb0b26 2006-04-01 devnull /* if we're out of messages, go back to first */
1657 cbeb0b26 2006-04-01 devnull /* if no first, return the fake first */
1658 5cdb1798 2005-10-29 devnull if(cur == nil){
1659 5cdb1798 2005-10-29 devnull if(top.child)
1660 5cdb1798 2005-10-29 devnull return top.child;
1661 5cdb1798 2005-10-29 devnull else
1662 5cdb1798 2005-10-29 devnull return &top;
1663 5cdb1798 2005-10-29 devnull }
1664 5cdb1798 2005-10-29 devnull return cur;
1665 5cdb1798 2005-10-29 devnull }
1666 5cdb1798 2005-10-29 devnull
1667 5cdb1798 2005-10-29 devnull Message*
1668 7e61af51 2006-02-12 devnull qcmd(Cmd *x, Message *m)
1669 5cdb1798 2005-10-29 devnull {
1670 7e61af51 2006-02-12 devnull USED(x);
1671 7e61af51 2006-02-12 devnull USED(m);
1672 7e61af51 2006-02-12 devnull
1673 5cdb1798 2005-10-29 devnull flushdeleted(nil);
1674 5cdb1798 2005-10-29 devnull
1675 5cdb1798 2005-10-29 devnull if(didopen)
1676 5cdb1798 2005-10-29 devnull closemb();
1677 5cdb1798 2005-10-29 devnull Bflush(&out);
1678 5cdb1798 2005-10-29 devnull
1679 5cdb1798 2005-10-29 devnull exitfs(0);
1680 cbeb0b26 2006-04-01 devnull return nil; /* not reached */
1681 5cdb1798 2005-10-29 devnull }
1682 5cdb1798 2005-10-29 devnull
1683 5cdb1798 2005-10-29 devnull Message*
1684 7e61af51 2006-02-12 devnull ycmd(Cmd *x, Message *m)
1685 5cdb1798 2005-10-29 devnull {
1686 7e61af51 2006-02-12 devnull USED(x);
1687 7e61af51 2006-02-12 devnull
1688 5cdb1798 2005-10-29 devnull doflush = 1;
1689 5cdb1798 2005-10-29 devnull
1690 5cdb1798 2005-10-29 devnull return icmd(nil, m);
1691 5cdb1798 2005-10-29 devnull }
1692 5cdb1798 2005-10-29 devnull
1693 5cdb1798 2005-10-29 devnull Message*
1694 7e61af51 2006-02-12 devnull xcmd(Cmd *x, Message *m)
1695 5cdb1798 2005-10-29 devnull {
1696 7e61af51 2006-02-12 devnull USED(x);
1697 7e61af51 2006-02-12 devnull USED(m);
1698 7e61af51 2006-02-12 devnull
1699 5cdb1798 2005-10-29 devnull exitfs(0);
1700 cbeb0b26 2006-04-01 devnull return nil; /* not reached */
1701 5cdb1798 2005-10-29 devnull }
1702 5cdb1798 2005-10-29 devnull
1703 5cdb1798 2005-10-29 devnull Message*
1704 7e61af51 2006-02-12 devnull eqcmd(Cmd *x, Message *m)
1705 5cdb1798 2005-10-29 devnull {
1706 7e61af51 2006-02-12 devnull USED(x);
1707 7e61af51 2006-02-12 devnull
1708 5cdb1798 2005-10-29 devnull if(m == &top)
1709 5cdb1798 2005-10-29 devnull Bprint(&out, "0\n");
1710 5cdb1798 2005-10-29 devnull else
1711 5cdb1798 2005-10-29 devnull Bprint(&out, "%d\n", m->id);
1712 5cdb1798 2005-10-29 devnull return nil;
1713 5cdb1798 2005-10-29 devnull }
1714 5cdb1798 2005-10-29 devnull
1715 5cdb1798 2005-10-29 devnull Message*
1716 7e61af51 2006-02-12 devnull dcmd(Cmd *x, Message *m)
1717 5cdb1798 2005-10-29 devnull {
1718 7e61af51 2006-02-12 devnull USED(x);
1719 7e61af51 2006-02-12 devnull
1720 5cdb1798 2005-10-29 devnull if(m == &top){
1721 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
1722 5cdb1798 2005-10-29 devnull return nil;
1723 5cdb1798 2005-10-29 devnull }
1724 5cdb1798 2005-10-29 devnull while(m->parent != &top)
1725 5cdb1798 2005-10-29 devnull m = m->parent;
1726 5cdb1798 2005-10-29 devnull m->deleted = 1;
1727 5cdb1798 2005-10-29 devnull return m;
1728 5cdb1798 2005-10-29 devnull }
1729 5cdb1798 2005-10-29 devnull
1730 5cdb1798 2005-10-29 devnull Message*
1731 7e61af51 2006-02-12 devnull ucmd(Cmd *x, Message *m)
1732 5cdb1798 2005-10-29 devnull {
1733 7e61af51 2006-02-12 devnull USED(x);
1734 7e61af51 2006-02-12 devnull
1735 5cdb1798 2005-10-29 devnull if(m == &top)
1736 5cdb1798 2005-10-29 devnull return nil;
1737 5cdb1798 2005-10-29 devnull while(m->parent != &top)
1738 5cdb1798 2005-10-29 devnull m = m->parent;
1739 5cdb1798 2005-10-29 devnull if(m->deleted < 0)
1740 5cdb1798 2005-10-29 devnull Bprint(&out, "!can't undelete, already flushed\n");
1741 5cdb1798 2005-10-29 devnull m->deleted = 0;
1742 5cdb1798 2005-10-29 devnull return m;
1743 5cdb1798 2005-10-29 devnull }
1744 5cdb1798 2005-10-29 devnull
1745 5cdb1798 2005-10-29 devnull
1746 5cdb1798 2005-10-29 devnull Message*
1747 7e61af51 2006-02-12 devnull icmd(Cmd *x, Message *m)
1748 5cdb1798 2005-10-29 devnull {
1749 5cdb1798 2005-10-29 devnull int n;
1750 de7b2cd7 2007-06-23 devnull char buf[1024];
1751 de7b2cd7 2007-06-23 devnull CFid *fd;
1752 5cdb1798 2005-10-29 devnull
1753 7e61af51 2006-02-12 devnull USED(x);
1754 de7b2cd7 2007-06-23 devnull snprint(buf, sizeof buf, "%s/ctl", mbname);
1755 de7b2cd7 2007-06-23 devnull fd = fsopen(mailfs, buf, OWRITE);
1756 de7b2cd7 2007-06-23 devnull if(fd){
1757 de7b2cd7 2007-06-23 devnull fswrite(fd, "refresh", 7);
1758 de7b2cd7 2007-06-23 devnull fsclose(fd);
1759 de7b2cd7 2007-06-23 devnull }
1760 5cdb1798 2005-10-29 devnull n = dir2message(&top, reverse);
1761 5cdb1798 2005-10-29 devnull if(n > 0)
1762 5cdb1798 2005-10-29 devnull Bprint(&out, "%d new message%s\n", n, plural(n));
1763 5cdb1798 2005-10-29 devnull return m;
1764 5cdb1798 2005-10-29 devnull }
1765 5cdb1798 2005-10-29 devnull
1766 5cdb1798 2005-10-29 devnull Message*
1767 7e61af51 2006-02-12 devnull helpcmd(Cmd *x, Message *m)
1768 5cdb1798 2005-10-29 devnull {
1769 5cdb1798 2005-10-29 devnull int i;
1770 5cdb1798 2005-10-29 devnull
1771 7e61af51 2006-02-12 devnull USED(x);
1772 5cdb1798 2005-10-29 devnull Bprint(&out, "Commands are of the form [<range>] <command> [args]\n");
1773 5cdb1798 2005-10-29 devnull Bprint(&out, "<range> := <addr> | <addr>','<addr>| 'g'<search>\n");
1774 5cdb1798 2005-10-29 devnull Bprint(&out, "<addr> := '.' | '$' | '^' | <number> | <search> | <addr>'+'<addr> | <addr>'-'<addr>\n");
1775 5cdb1798 2005-10-29 devnull Bprint(&out, "<search> := '/'<regexp>'/' | '?'<regexp>'?' | '%%'<regexp>'%%'\n");
1776 5cdb1798 2005-10-29 devnull Bprint(&out, "<command> :=\n");
1777 5cdb1798 2005-10-29 devnull for(i = 0; cmdtab[i].cmd != nil; i++)
1778 5cdb1798 2005-10-29 devnull Bprint(&out, "%s\n", cmdtab[i].help);
1779 5cdb1798 2005-10-29 devnull return m;
1780 5cdb1798 2005-10-29 devnull }
1781 5cdb1798 2005-10-29 devnull
1782 5cdb1798 2005-10-29 devnull int
1783 5cdb1798 2005-10-29 devnull tomailer(char **av)
1784 5cdb1798 2005-10-29 devnull {
1785 7e61af51 2006-02-12 devnull static char *marshal;
1786 5cdb1798 2005-10-29 devnull Waitmsg *w;
1787 5cdb1798 2005-10-29 devnull int pid, i;
1788 5cdb1798 2005-10-29 devnull
1789 7e61af51 2006-02-12 devnull if(marshal == nil)
1790 7e61af51 2006-02-12 devnull marshal = unsharp("#9/bin/upas/marshal");
1791 7e61af51 2006-02-12 devnull
1792 cbeb0b26 2006-04-01 devnull /* start the mailer and get out of the way */
1793 5cdb1798 2005-10-29 devnull switch(pid = fork()){
1794 5cdb1798 2005-10-29 devnull case -1:
1795 5cdb1798 2005-10-29 devnull fprint(2, "can't fork: %r\n");
1796 5cdb1798 2005-10-29 devnull return -1;
1797 5cdb1798 2005-10-29 devnull case 0:
1798 7e61af51 2006-02-12 devnull Bprint(&out, "!%s", marshal);
1799 5cdb1798 2005-10-29 devnull for(i = 1; av[i]; i++){
1800 5cdb1798 2005-10-29 devnull if(strchr(av[i], ' ') != nil)
1801 5cdb1798 2005-10-29 devnull Bprint(&out, " '%s'", av[i]);
1802 5cdb1798 2005-10-29 devnull else
1803 5cdb1798 2005-10-29 devnull Bprint(&out, " %s", av[i]);
1804 5cdb1798 2005-10-29 devnull }
1805 5cdb1798 2005-10-29 devnull Bprint(&out, "\n");
1806 5cdb1798 2005-10-29 devnull Bflush(&out);
1807 5cdb1798 2005-10-29 devnull av[0] = "marshal";
1808 5cdb1798 2005-10-29 devnull chdir(wd);
1809 7e61af51 2006-02-12 devnull exec(marshal, av);
1810 7e61af51 2006-02-12 devnull fprint(2, "couldn't exec %s\n", marshal);
1811 5cdb1798 2005-10-29 devnull threadexits(0);
1812 5cdb1798 2005-10-29 devnull default:
1813 5cdb1798 2005-10-29 devnull w = wait();
1814 5cdb1798 2005-10-29 devnull if(w == nil){
1815 5cdb1798 2005-10-29 devnull if(interrupted)
1816 5cdb1798 2005-10-29 devnull postnote(PNPROC, pid, "die");
1817 5cdb1798 2005-10-29 devnull waitpid();
1818 5cdb1798 2005-10-29 devnull return -1;
1819 5cdb1798 2005-10-29 devnull }
1820 5cdb1798 2005-10-29 devnull if(w->msg[0]){
1821 5cdb1798 2005-10-29 devnull fprint(2, "mailer failed: %s\n", w->msg);
1822 5cdb1798 2005-10-29 devnull free(w);
1823 5cdb1798 2005-10-29 devnull return -1;
1824 5cdb1798 2005-10-29 devnull }
1825 5cdb1798 2005-10-29 devnull free(w);
1826 5cdb1798 2005-10-29 devnull Bprint(&out, "!\n");
1827 5cdb1798 2005-10-29 devnull break;
1828 5cdb1798 2005-10-29 devnull }
1829 5cdb1798 2005-10-29 devnull return 0;
1830 5cdb1798 2005-10-29 devnull }
1831 5cdb1798 2005-10-29 devnull
1832 cbeb0b26 2006-04-01 devnull /* */
1833 cbeb0b26 2006-04-01 devnull /* like tokenize but obey "" quoting */
1834 cbeb0b26 2006-04-01 devnull /* */
1835 5cdb1798 2005-10-29 devnull int
1836 5cdb1798 2005-10-29 devnull tokenize822(char *str, char **args, int max)
1837 5cdb1798 2005-10-29 devnull {
1838 5cdb1798 2005-10-29 devnull int na;
1839 5cdb1798 2005-10-29 devnull int intok = 0, inquote = 0;
1840 5cdb1798 2005-10-29 devnull
1841 5cdb1798 2005-10-29 devnull if(max <= 0)
1842 5cdb1798 2005-10-29 devnull return 0;
1843 5cdb1798 2005-10-29 devnull for(na=0; ;str++)
1844 5cdb1798 2005-10-29 devnull switch(*str) {
1845 5cdb1798 2005-10-29 devnull case ' ':
1846 5cdb1798 2005-10-29 devnull case '\t':
1847 5cdb1798 2005-10-29 devnull if(inquote)
1848 5cdb1798 2005-10-29 devnull goto Default;
1849 5cdb1798 2005-10-29 devnull /* fall through */
1850 5cdb1798 2005-10-29 devnull case '\n':
1851 5cdb1798 2005-10-29 devnull *str = 0;
1852 5cdb1798 2005-10-29 devnull if(!intok)
1853 5cdb1798 2005-10-29 devnull continue;
1854 5cdb1798 2005-10-29 devnull intok = 0;
1855 5cdb1798 2005-10-29 devnull if(na < max)
1856 5cdb1798 2005-10-29 devnull continue;
1857 5cdb1798 2005-10-29 devnull /* fall through */
1858 5cdb1798 2005-10-29 devnull case 0:
1859 5cdb1798 2005-10-29 devnull return na;
1860 5cdb1798 2005-10-29 devnull case '"':
1861 5cdb1798 2005-10-29 devnull inquote ^= 1;
1862 5cdb1798 2005-10-29 devnull /* fall through */
1863 5cdb1798 2005-10-29 devnull Default:
1864 5cdb1798 2005-10-29 devnull default:
1865 5cdb1798 2005-10-29 devnull if(intok)
1866 5cdb1798 2005-10-29 devnull continue;
1867 5cdb1798 2005-10-29 devnull args[na++] = str;
1868 5cdb1798 2005-10-29 devnull intok = 1;
1869 5cdb1798 2005-10-29 devnull }
1870 5cdb1798 2005-10-29 devnull return 0; /* can't get here; silence compiler */
1871 5cdb1798 2005-10-29 devnull }
1872 5cdb1798 2005-10-29 devnull
1873 5cdb1798 2005-10-29 devnull Message*
1874 5cdb1798 2005-10-29 devnull rcmd(Cmd *c, Message *m)
1875 5cdb1798 2005-10-29 devnull {
1876 5cdb1798 2005-10-29 devnull char *av[128];
1877 5cdb1798 2005-10-29 devnull int i, ai = 1;
1878 5cdb1798 2005-10-29 devnull Message *nm;
1879 5cdb1798 2005-10-29 devnull char *addr;
1880 5cdb1798 2005-10-29 devnull String *path = nil;
1881 5cdb1798 2005-10-29 devnull String *rpath;
1882 5cdb1798 2005-10-29 devnull String *subject = nil;
1883 5cdb1798 2005-10-29 devnull String *from;
1884 5cdb1798 2005-10-29 devnull
1885 5cdb1798 2005-10-29 devnull if(m == &top){
1886 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
1887 5cdb1798 2005-10-29 devnull return nil;
1888 5cdb1798 2005-10-29 devnull }
1889 5cdb1798 2005-10-29 devnull
1890 5cdb1798 2005-10-29 devnull addr = nil;
1891 5cdb1798 2005-10-29 devnull for(nm = m; nm != &top; nm = nm->parent){
1892 5cdb1798 2005-10-29 devnull if(*nm->replyto != 0){
1893 5cdb1798 2005-10-29 devnull addr = nm->replyto;
1894 5cdb1798 2005-10-29 devnull break;
1895 5cdb1798 2005-10-29 devnull }
1896 5cdb1798 2005-10-29 devnull }
1897 5cdb1798 2005-10-29 devnull if(addr == nil){
1898 5cdb1798 2005-10-29 devnull Bprint(&out, "!no reply address\n");
1899 5cdb1798 2005-10-29 devnull return nil;
1900 5cdb1798 2005-10-29 devnull }
1901 5cdb1798 2005-10-29 devnull
1902 5cdb1798 2005-10-29 devnull if(nm == &top){
1903 5cdb1798 2005-10-29 devnull print("!noone to reply to\n");
1904 5cdb1798 2005-10-29 devnull return nil;
1905 5cdb1798 2005-10-29 devnull }
1906 5cdb1798 2005-10-29 devnull
1907 5cdb1798 2005-10-29 devnull for(nm = m; nm != &top; nm = nm->parent){
1908 5cdb1798 2005-10-29 devnull if(*nm->subject){
1909 5cdb1798 2005-10-29 devnull av[ai++] = "-s";
1910 5cdb1798 2005-10-29 devnull subject = addrecolon(nm->subject);
1911 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(subject);;
1912 5cdb1798 2005-10-29 devnull break;
1913 5cdb1798 2005-10-29 devnull }
1914 5cdb1798 2005-10-29 devnull }
1915 5cdb1798 2005-10-29 devnull
1916 5cdb1798 2005-10-29 devnull av[ai++] = "-R";
1917 5cdb1798 2005-10-29 devnull rpath = rooted(s_clone(m->path));
1918 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(rpath);
1919 5cdb1798 2005-10-29 devnull
1920 5cdb1798 2005-10-29 devnull if(strchr(c->av[0], 'f') != nil){
1921 5cdb1798 2005-10-29 devnull fcmd(c, m);
1922 5cdb1798 2005-10-29 devnull av[ai++] = "-F";
1923 5cdb1798 2005-10-29 devnull }
1924 5cdb1798 2005-10-29 devnull
1925 5cdb1798 2005-10-29 devnull if(strchr(c->av[0], 'R') != nil){
1926 5cdb1798 2005-10-29 devnull av[ai++] = "-t";
1927 5cdb1798 2005-10-29 devnull av[ai++] = "message/rfc822";
1928 5cdb1798 2005-10-29 devnull av[ai++] = "-A";
1929 5cdb1798 2005-10-29 devnull path = rooted(extendpath(m->path, "raw"));
1930 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(path);
1931 5cdb1798 2005-10-29 devnull }
1932 5cdb1798 2005-10-29 devnull
1933 5cdb1798 2005-10-29 devnull for(i = 1; i < c->an && ai < nelem(av)-1; i++)
1934 5cdb1798 2005-10-29 devnull av[ai++] = c->av[i];
1935 5cdb1798 2005-10-29 devnull from = s_copy(addr);
1936 5cdb1798 2005-10-29 devnull ai += tokenize822(s_to_c(from), &av[ai], nelem(av) - ai);
1937 5cdb1798 2005-10-29 devnull av[ai] = 0;
1938 5cdb1798 2005-10-29 devnull if(tomailer(av) < 0)
1939 5cdb1798 2005-10-29 devnull m = nil;
1940 5cdb1798 2005-10-29 devnull s_free(path);
1941 5cdb1798 2005-10-29 devnull s_free(rpath);
1942 5cdb1798 2005-10-29 devnull s_free(subject);
1943 5cdb1798 2005-10-29 devnull s_free(from);
1944 5cdb1798 2005-10-29 devnull return m;
1945 5cdb1798 2005-10-29 devnull }
1946 5cdb1798 2005-10-29 devnull
1947 5cdb1798 2005-10-29 devnull Message*
1948 5cdb1798 2005-10-29 devnull mcmd(Cmd *c, Message *m)
1949 5cdb1798 2005-10-29 devnull {
1950 5cdb1798 2005-10-29 devnull char **av;
1951 5cdb1798 2005-10-29 devnull int i, ai;
1952 5cdb1798 2005-10-29 devnull String *path;
1953 5cdb1798 2005-10-29 devnull
1954 5cdb1798 2005-10-29 devnull if(m == &top){
1955 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
1956 5cdb1798 2005-10-29 devnull return nil;
1957 5cdb1798 2005-10-29 devnull }
1958 5cdb1798 2005-10-29 devnull
1959 5cdb1798 2005-10-29 devnull if(c->an < 2){
1960 5cdb1798 2005-10-29 devnull fprint(2, "!usage: M list-of addresses\n");
1961 5cdb1798 2005-10-29 devnull return nil;
1962 5cdb1798 2005-10-29 devnull }
1963 5cdb1798 2005-10-29 devnull
1964 5cdb1798 2005-10-29 devnull ai = 1;
1965 5cdb1798 2005-10-29 devnull av = malloc(sizeof(char*)*(c->an + 8));
1966 5cdb1798 2005-10-29 devnull
1967 5cdb1798 2005-10-29 devnull av[ai++] = "-t";
1968 5cdb1798 2005-10-29 devnull if(m->parent == &top)
1969 5cdb1798 2005-10-29 devnull av[ai++] = "message/rfc822";
1970 5cdb1798 2005-10-29 devnull else
1971 5cdb1798 2005-10-29 devnull av[ai++] = "mime";
1972 5cdb1798 2005-10-29 devnull
1973 5cdb1798 2005-10-29 devnull av[ai++] = "-A";
1974 5cdb1798 2005-10-29 devnull path = rooted(extendpath(m->path, "raw"));
1975 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(path);
1976 5cdb1798 2005-10-29 devnull
1977 5cdb1798 2005-10-29 devnull if(strchr(c->av[0], 'M') == nil)
1978 5cdb1798 2005-10-29 devnull av[ai++] = "-n";
1979 5cdb1798 2005-10-29 devnull
1980 5cdb1798 2005-10-29 devnull for(i = 1; i < c->an; i++)
1981 5cdb1798 2005-10-29 devnull av[ai++] = c->av[i];
1982 5cdb1798 2005-10-29 devnull av[ai] = 0;
1983 5cdb1798 2005-10-29 devnull
1984 5cdb1798 2005-10-29 devnull if(tomailer(av) < 0)
1985 5cdb1798 2005-10-29 devnull m = nil;
1986 5cdb1798 2005-10-29 devnull if(path != nil)
1987 5cdb1798 2005-10-29 devnull s_free(path);
1988 5cdb1798 2005-10-29 devnull free(av);
1989 5cdb1798 2005-10-29 devnull return m;
1990 5cdb1798 2005-10-29 devnull }
1991 5cdb1798 2005-10-29 devnull
1992 5cdb1798 2005-10-29 devnull Message*
1993 5cdb1798 2005-10-29 devnull acmd(Cmd *c, Message *m)
1994 5cdb1798 2005-10-29 devnull {
1995 5cdb1798 2005-10-29 devnull char *av[128];
1996 5cdb1798 2005-10-29 devnull int i, ai;
1997 5cdb1798 2005-10-29 devnull String *from, *to, *cc, *path = nil, *subject = nil;
1998 5cdb1798 2005-10-29 devnull
1999 5cdb1798 2005-10-29 devnull if(m == &top){
2000 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
2001 5cdb1798 2005-10-29 devnull return nil;
2002 5cdb1798 2005-10-29 devnull }
2003 5cdb1798 2005-10-29 devnull
2004 5cdb1798 2005-10-29 devnull ai = 1;
2005 5cdb1798 2005-10-29 devnull if(*m->subject){
2006 5cdb1798 2005-10-29 devnull av[ai++] = "-s";
2007 5cdb1798 2005-10-29 devnull subject = addrecolon(m->subject);
2008 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(subject);
2009 5cdb1798 2005-10-29 devnull }
2010 5cdb1798 2005-10-29 devnull
2011 5cdb1798 2005-10-29 devnull if(strchr(c->av[0], 'A') != nil){
2012 5cdb1798 2005-10-29 devnull av[ai++] = "-t";
2013 5cdb1798 2005-10-29 devnull av[ai++] = "message/rfc822";
2014 5cdb1798 2005-10-29 devnull av[ai++] = "-A";
2015 5cdb1798 2005-10-29 devnull path = rooted(extendpath(m->path, "raw"));
2016 5cdb1798 2005-10-29 devnull av[ai++] = s_to_c(path);
2017 5cdb1798 2005-10-29 devnull }
2018 5cdb1798 2005-10-29 devnull
2019 5cdb1798 2005-10-29 devnull for(i = 1; i < c->an && ai < nelem(av)-1; i++)
2020 5cdb1798 2005-10-29 devnull av[ai++] = c->av[i];
2021 5cdb1798 2005-10-29 devnull from = s_copy(m->from);
2022 5cdb1798 2005-10-29 devnull ai += tokenize822(s_to_c(from), &av[ai], nelem(av) - ai);
2023 5cdb1798 2005-10-29 devnull to = s_copy(m->to);
2024 5cdb1798 2005-10-29 devnull ai += tokenize822(s_to_c(to), &av[ai], nelem(av) - ai);
2025 5cdb1798 2005-10-29 devnull cc = s_copy(m->cc);
2026 5cdb1798 2005-10-29 devnull ai += tokenize822(s_to_c(cc), &av[ai], nelem(av) - ai);
2027 5cdb1798 2005-10-29 devnull av[ai] = 0;
2028 5cdb1798 2005-10-29 devnull if(tomailer(av) < 0)
2029 5cdb1798 2005-10-29 devnull return nil;
2030 5cdb1798 2005-10-29 devnull s_free(from);
2031 5cdb1798 2005-10-29 devnull s_free(to);
2032 5cdb1798 2005-10-29 devnull s_free(cc);
2033 5cdb1798 2005-10-29 devnull s_free(subject);
2034 5cdb1798 2005-10-29 devnull s_free(path);
2035 5cdb1798 2005-10-29 devnull return m;
2036 5cdb1798 2005-10-29 devnull }
2037 5cdb1798 2005-10-29 devnull
2038 5cdb1798 2005-10-29 devnull String *
2039 5cdb1798 2005-10-29 devnull relpath(char *path, String *to)
2040 5cdb1798 2005-10-29 devnull {
2041 5cdb1798 2005-10-29 devnull if (*path=='/' || strncmp(path, "./", 2) == 0
2042 5cdb1798 2005-10-29 devnull || strncmp(path, "../", 3) == 0) {
2043 5cdb1798 2005-10-29 devnull to = s_append(to, path);
2044 5cdb1798 2005-10-29 devnull } else if(mbpath) {
2045 5cdb1798 2005-10-29 devnull to = s_append(to, s_to_c(mbpath));
2046 5cdb1798 2005-10-29 devnull to->ptr = strrchr(to->base, '/')+1;
2047 5cdb1798 2005-10-29 devnull s_append(to, path);
2048 5cdb1798 2005-10-29 devnull }
2049 5cdb1798 2005-10-29 devnull return to;
2050 5cdb1798 2005-10-29 devnull }
2051 5cdb1798 2005-10-29 devnull
2052 5cdb1798 2005-10-29 devnull int
2053 5cdb1798 2005-10-29 devnull appendtofile(Message *m, char *part, char *base, int mbox)
2054 5cdb1798 2005-10-29 devnull {
2055 5cdb1798 2005-10-29 devnull String *file, *h;
2056 5cdb1798 2005-10-29 devnull int in, out, rv;
2057 5cdb1798 2005-10-29 devnull
2058 5cdb1798 2005-10-29 devnull file = extendpath(m->path, part);
2059 5cdb1798 2005-10-29 devnull in = open(s_to_c(file), OREAD);
2060 5cdb1798 2005-10-29 devnull if(in < 0){
2061 5cdb1798 2005-10-29 devnull fprint(2, "!message disappeared\n");
2062 5cdb1798 2005-10-29 devnull return -1;
2063 5cdb1798 2005-10-29 devnull }
2064 5cdb1798 2005-10-29 devnull
2065 5cdb1798 2005-10-29 devnull s_reset(file);
2066 5cdb1798 2005-10-29 devnull
2067 5cdb1798 2005-10-29 devnull relpath(base, file);
2068 5cdb1798 2005-10-29 devnull if(sysisdir(s_to_c(file))){
2069 5cdb1798 2005-10-29 devnull s_append(file, "/");
2070 5cdb1798 2005-10-29 devnull if(m->filename && strchr(m->filename, '/') == nil)
2071 5cdb1798 2005-10-29 devnull s_append(file, m->filename);
2072 5cdb1798 2005-10-29 devnull else {
2073 5cdb1798 2005-10-29 devnull s_append(file, "att.XXXXXXXXXXX");
2074 5cdb1798 2005-10-29 devnull mktemp(s_to_c(file));
2075 5cdb1798 2005-10-29 devnull }
2076 5cdb1798 2005-10-29 devnull }
2077 5cdb1798 2005-10-29 devnull if(mbox)
2078 5cdb1798 2005-10-29 devnull out = open(s_to_c(file), OWRITE);
2079 5cdb1798 2005-10-29 devnull else
2080 5cdb1798 2005-10-29 devnull out = open(s_to_c(file), OWRITE|OTRUNC);
2081 5cdb1798 2005-10-29 devnull if(out < 0){
2082 5cdb1798 2005-10-29 devnull out = create(s_to_c(file), OWRITE, 0666);
2083 5cdb1798 2005-10-29 devnull if(out < 0){
2084 5cdb1798 2005-10-29 devnull fprint(2, "!can't open %s: %r\n", s_to_c(file));
2085 5cdb1798 2005-10-29 devnull close(in);
2086 5cdb1798 2005-10-29 devnull s_free(file);
2087 5cdb1798 2005-10-29 devnull return -1;
2088 5cdb1798 2005-10-29 devnull }
2089 5cdb1798 2005-10-29 devnull }
2090 5cdb1798 2005-10-29 devnull if(mbox)
2091 5cdb1798 2005-10-29 devnull seek(out, 0, 2);
2092 5cdb1798 2005-10-29 devnull
2093 cbeb0b26 2006-04-01 devnull /* put on a 'From ' line */
2094 5cdb1798 2005-10-29 devnull if(mbox){
2095 5cdb1798 2005-10-29 devnull while(m->parent != &top)
2096 5cdb1798 2005-10-29 devnull m = m->parent;
2097 5cdb1798 2005-10-29 devnull h = file2string(m->path, "unixheader");
2098 5cdb1798 2005-10-29 devnull fprint(out, "%s", s_to_c(h));
2099 5cdb1798 2005-10-29 devnull s_free(h);
2100 5cdb1798 2005-10-29 devnull }
2101 5cdb1798 2005-10-29 devnull
2102 cbeb0b26 2006-04-01 devnull /* copy the message escaping what we have to ad adding newlines if we have to */
2103 5cdb1798 2005-10-29 devnull if(mbox)
2104 5cdb1798 2005-10-29 devnull rv = appendfiletombox(in, out);
2105 5cdb1798 2005-10-29 devnull else
2106 5cdb1798 2005-10-29 devnull rv = appendfiletofile(in, out);
2107 5cdb1798 2005-10-29 devnull
2108 5cdb1798 2005-10-29 devnull close(in);
2109 5cdb1798 2005-10-29 devnull close(out);
2110 5cdb1798 2005-10-29 devnull
2111 5cdb1798 2005-10-29 devnull if(rv >= 0)
2112 5cdb1798 2005-10-29 devnull print("!saved in %s\n", s_to_c(file));
2113 5cdb1798 2005-10-29 devnull s_free(file);
2114 5cdb1798 2005-10-29 devnull return rv;
2115 5cdb1798 2005-10-29 devnull }
2116 5cdb1798 2005-10-29 devnull
2117 5cdb1798 2005-10-29 devnull Message*
2118 5cdb1798 2005-10-29 devnull scmd(Cmd *c, Message *m)
2119 5cdb1798 2005-10-29 devnull {
2120 1ea614ff 2006-02-15 devnull char buf[256];
2121 1ea614ff 2006-02-15 devnull CFid *fd;
2122 1ea614ff 2006-02-15 devnull char *file, *msg;
2123 5cdb1798 2005-10-29 devnull
2124 5cdb1798 2005-10-29 devnull if(m == &top){
2125 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
2126 5cdb1798 2005-10-29 devnull return nil;
2127 5cdb1798 2005-10-29 devnull }
2128 5cdb1798 2005-10-29 devnull
2129 5cdb1798 2005-10-29 devnull switch(c->an){
2130 5cdb1798 2005-10-29 devnull case 1:
2131 5cdb1798 2005-10-29 devnull file = "stored";
2132 5cdb1798 2005-10-29 devnull break;
2133 5cdb1798 2005-10-29 devnull case 2:
2134 5cdb1798 2005-10-29 devnull file = c->av[1];
2135 5cdb1798 2005-10-29 devnull break;
2136 5cdb1798 2005-10-29 devnull default:
2137 5cdb1798 2005-10-29 devnull fprint(2, "!usage: s filename\n");
2138 5cdb1798 2005-10-29 devnull return nil;
2139 5cdb1798 2005-10-29 devnull }
2140 5cdb1798 2005-10-29 devnull
2141 1ea614ff 2006-02-15 devnull if(file[0] == '/' || (file[0]=='.' && file[1]=='/')){
2142 1ea614ff 2006-02-15 devnull if(appendtofile(m, "raw", file, 1) < 0)
2143 1ea614ff 2006-02-15 devnull return nil;
2144 1ea614ff 2006-02-15 devnull }else{
2145 1ea614ff 2006-02-15 devnull snprint(buf, sizeof buf, "%s/ctl", mbname);
2146 1ea614ff 2006-02-15 devnull if((fd = fsopen(mailfs, buf, OWRITE)) == nil)
2147 1ea614ff 2006-02-15 devnull return nil;
2148 1ea614ff 2006-02-15 devnull msg = strrchr(s_to_c(m->path), '/');
2149 1ea614ff 2006-02-15 devnull if(msg == nil)
2150 1ea614ff 2006-02-15 devnull msg = s_to_c(m->path);
2151 1ea614ff 2006-02-15 devnull else
2152 1ea614ff 2006-02-15 devnull msg++;
2153 1ea614ff 2006-02-15 devnull if(fsprint(fd, "save %s %s", file, msg) < 0){
2154 1ea614ff 2006-02-15 devnull fsclose(fd);
2155 1ea614ff 2006-02-15 devnull return nil;
2156 1ea614ff 2006-02-15 devnull }
2157 1ea614ff 2006-02-15 devnull fsclose(fd);
2158 1ea614ff 2006-02-15 devnull }
2159 5cdb1798 2005-10-29 devnull m->stored = 1;
2160 5cdb1798 2005-10-29 devnull return m;
2161 5cdb1798 2005-10-29 devnull }
2162 5cdb1798 2005-10-29 devnull
2163 5cdb1798 2005-10-29 devnull Message*
2164 5cdb1798 2005-10-29 devnull wcmd(Cmd *c, Message *m)
2165 5cdb1798 2005-10-29 devnull {
2166 5cdb1798 2005-10-29 devnull char *file;
2167 5cdb1798 2005-10-29 devnull
2168 5cdb1798 2005-10-29 devnull if(m == &top){
2169 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
2170 5cdb1798 2005-10-29 devnull return nil;
2171 5cdb1798 2005-10-29 devnull }
2172 5cdb1798 2005-10-29 devnull
2173 5cdb1798 2005-10-29 devnull switch(c->an){
2174 5cdb1798 2005-10-29 devnull case 2:
2175 5cdb1798 2005-10-29 devnull file = c->av[1];
2176 5cdb1798 2005-10-29 devnull break;
2177 5cdb1798 2005-10-29 devnull case 1:
2178 5cdb1798 2005-10-29 devnull if(*m->filename == 0){
2179 5cdb1798 2005-10-29 devnull fprint(2, "!usage: w filename\n");
2180 5cdb1798 2005-10-29 devnull return nil;
2181 5cdb1798 2005-10-29 devnull }
2182 5cdb1798 2005-10-29 devnull file = strrchr(m->filename, '/');
2183 5cdb1798 2005-10-29 devnull if(file != nil)
2184 5cdb1798 2005-10-29 devnull file++;
2185 5cdb1798 2005-10-29 devnull else
2186 5cdb1798 2005-10-29 devnull file = m->filename;
2187 5cdb1798 2005-10-29 devnull break;
2188 5cdb1798 2005-10-29 devnull default:
2189 5cdb1798 2005-10-29 devnull fprint(2, "!usage: w filename\n");
2190 5cdb1798 2005-10-29 devnull return nil;
2191 5cdb1798 2005-10-29 devnull }
2192 5cdb1798 2005-10-29 devnull
2193 5cdb1798 2005-10-29 devnull if(appendtofile(m, "body", file, 0) < 0)
2194 5cdb1798 2005-10-29 devnull return nil;
2195 5cdb1798 2005-10-29 devnull m->stored = 1;
2196 5cdb1798 2005-10-29 devnull return m;
2197 5cdb1798 2005-10-29 devnull }
2198 5cdb1798 2005-10-29 devnull
2199 5cdb1798 2005-10-29 devnull char *specialfile[] =
2200 5cdb1798 2005-10-29 devnull {
2201 5cdb1798 2005-10-29 devnull "pipeto",
2202 5cdb1798 2005-10-29 devnull "pipefrom",
2203 5cdb1798 2005-10-29 devnull "L.mbox",
2204 5cdb1798 2005-10-29 devnull "forward",
2205 5cdb1798 2005-10-29 devnull "names"
2206 5cdb1798 2005-10-29 devnull };
2207 5cdb1798 2005-10-29 devnull
2208 cbeb0b26 2006-04-01 devnull /* return 1 if this is a special file */
2209 5cdb1798 2005-10-29 devnull static int
2210 5cdb1798 2005-10-29 devnull special(String *s)
2211 5cdb1798 2005-10-29 devnull {
2212 5cdb1798 2005-10-29 devnull char *p;
2213 5cdb1798 2005-10-29 devnull int i;
2214 5cdb1798 2005-10-29 devnull
2215 5cdb1798 2005-10-29 devnull p = strrchr(s_to_c(s), '/');
2216 5cdb1798 2005-10-29 devnull if(p == nil)
2217 5cdb1798 2005-10-29 devnull p = s_to_c(s);
2218 5cdb1798 2005-10-29 devnull else
2219 5cdb1798 2005-10-29 devnull p++;
2220 5cdb1798 2005-10-29 devnull for(i = 0; i < nelem(specialfile); i++)
2221 5cdb1798 2005-10-29 devnull if(strcmp(p, specialfile[i]) == 0)
2222 5cdb1798 2005-10-29 devnull return 1;
2223 5cdb1798 2005-10-29 devnull return 0;
2224 5cdb1798 2005-10-29 devnull }
2225 5cdb1798 2005-10-29 devnull
2226 cbeb0b26 2006-04-01 devnull /* open the folder using the recipients account name */
2227 5cdb1798 2005-10-29 devnull static String*
2228 5cdb1798 2005-10-29 devnull foldername(char *rcvr)
2229 5cdb1798 2005-10-29 devnull {
2230 5cdb1798 2005-10-29 devnull char *p;
2231 5cdb1798 2005-10-29 devnull int c;
2232 5cdb1798 2005-10-29 devnull String *file;
2233 5cdb1798 2005-10-29 devnull Dir *d;
2234 5cdb1798 2005-10-29 devnull int scarey;
2235 5cdb1798 2005-10-29 devnull
2236 5cdb1798 2005-10-29 devnull file = s_new();
2237 5cdb1798 2005-10-29 devnull mboxpath("f", user, file, 0);
2238 5cdb1798 2005-10-29 devnull d = dirstat(s_to_c(file));
2239 5cdb1798 2005-10-29 devnull
2240 cbeb0b26 2006-04-01 devnull /* if $mail/f exists, store there, otherwise in $mail */
2241 5cdb1798 2005-10-29 devnull s_restart(file);
2242 5cdb1798 2005-10-29 devnull if(d && d->qid.type == QTDIR){
2243 5cdb1798 2005-10-29 devnull scarey = 0;
2244 5cdb1798 2005-10-29 devnull s_append(file, "f/");
2245 5cdb1798 2005-10-29 devnull } else {
2246 5cdb1798 2005-10-29 devnull scarey = 1;
2247 5cdb1798 2005-10-29 devnull }
2248 5cdb1798 2005-10-29 devnull free(d);
2249 5cdb1798 2005-10-29 devnull
2250 5cdb1798 2005-10-29 devnull p = strrchr(rcvr, '!');
2251 5cdb1798 2005-10-29 devnull if(p != nil)
2252 5cdb1798 2005-10-29 devnull rcvr = p+1;
2253 5cdb1798 2005-10-29 devnull
2254 5cdb1798 2005-10-29 devnull while(*rcvr && *rcvr != '@'){
2255 5cdb1798 2005-10-29 devnull c = *rcvr++;
2256 5cdb1798 2005-10-29 devnull if(c == '/')
2257 5cdb1798 2005-10-29 devnull c = '_';
2258 5cdb1798 2005-10-29 devnull s_putc(file, c);
2259 5cdb1798 2005-10-29 devnull }
2260 5cdb1798 2005-10-29 devnull s_terminate(file);
2261 5cdb1798 2005-10-29 devnull
2262 5cdb1798 2005-10-29 devnull if(scarey && special(file)){
2263 5cdb1798 2005-10-29 devnull fprint(2, "!won't overwrite %s\n", s_to_c(file));
2264 5cdb1798 2005-10-29 devnull s_free(file);
2265 5cdb1798 2005-10-29 devnull return nil;
2266 5cdb1798 2005-10-29 devnull }
2267 5cdb1798 2005-10-29 devnull
2268 5cdb1798 2005-10-29 devnull return file;
2269 5cdb1798 2005-10-29 devnull }
2270 5cdb1798 2005-10-29 devnull
2271 5cdb1798 2005-10-29 devnull Message*
2272 5cdb1798 2005-10-29 devnull fcmd(Cmd *c, Message *m)
2273 5cdb1798 2005-10-29 devnull {
2274 5cdb1798 2005-10-29 devnull String *folder;
2275 5cdb1798 2005-10-29 devnull
2276 5cdb1798 2005-10-29 devnull if(c->an > 1){
2277 5cdb1798 2005-10-29 devnull fprint(2, "!usage: f takes no arguments\n");
2278 5cdb1798 2005-10-29 devnull return nil;
2279 5cdb1798 2005-10-29 devnull }
2280 5cdb1798 2005-10-29 devnull
2281 5cdb1798 2005-10-29 devnull if(m == &top){
2282 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
2283 5cdb1798 2005-10-29 devnull return nil;
2284 5cdb1798 2005-10-29 devnull }
2285 5cdb1798 2005-10-29 devnull
2286 5cdb1798 2005-10-29 devnull folder = foldername(m->from);
2287 5cdb1798 2005-10-29 devnull if(folder == nil)
2288 5cdb1798 2005-10-29 devnull return nil;
2289 5cdb1798 2005-10-29 devnull
2290 5cdb1798 2005-10-29 devnull if(appendtofile(m, "raw", s_to_c(folder), 1) < 0){
2291 5cdb1798 2005-10-29 devnull s_free(folder);
2292 5cdb1798 2005-10-29 devnull return nil;
2293 5cdb1798 2005-10-29 devnull }
2294 5cdb1798 2005-10-29 devnull s_free(folder);
2295 5cdb1798 2005-10-29 devnull
2296 5cdb1798 2005-10-29 devnull m->stored = 1;
2297 5cdb1798 2005-10-29 devnull return m;
2298 5cdb1798 2005-10-29 devnull }
2299 5cdb1798 2005-10-29 devnull
2300 5cdb1798 2005-10-29 devnull void
2301 7e61af51 2006-02-12 devnull system(char *cmd, char **av, int in)
2302 5cdb1798 2005-10-29 devnull {
2303 5cdb1798 2005-10-29 devnull int pid;
2304 5cdb1798 2005-10-29 devnull
2305 5cdb1798 2005-10-29 devnull switch(pid=fork()){
2306 5cdb1798 2005-10-29 devnull case -1:
2307 5cdb1798 2005-10-29 devnull return;
2308 5cdb1798 2005-10-29 devnull case 0:
2309 7e61af51 2006-02-12 devnull if(strcmp(cmd, "rc") == 0)
2310 7e61af51 2006-02-12 devnull cmd = unsharp("#9/bin/rc");
2311 5cdb1798 2005-10-29 devnull if(in >= 0){
2312 5cdb1798 2005-10-29 devnull close(0);
2313 5cdb1798 2005-10-29 devnull dup(in, 0);
2314 5cdb1798 2005-10-29 devnull close(in);
2315 5cdb1798 2005-10-29 devnull }
2316 5cdb1798 2005-10-29 devnull if(wd[0] != 0)
2317 5cdb1798 2005-10-29 devnull chdir(wd);
2318 5cdb1798 2005-10-29 devnull exec(cmd, av);
2319 5cdb1798 2005-10-29 devnull fprint(2, "!couldn't exec %s\n", cmd);
2320 5cdb1798 2005-10-29 devnull threadexits(0);
2321 5cdb1798 2005-10-29 devnull default:
2322 5cdb1798 2005-10-29 devnull if(in >= 0)
2323 5cdb1798 2005-10-29 devnull close(in);
2324 5cdb1798 2005-10-29 devnull while(waitpid() < 0){
2325 5cdb1798 2005-10-29 devnull if(!interrupted)
2326 5cdb1798 2005-10-29 devnull break;
2327 5cdb1798 2005-10-29 devnull postnote(PNPROC, pid, "die");
2328 5cdb1798 2005-10-29 devnull continue;
2329 5cdb1798 2005-10-29 devnull }
2330 5cdb1798 2005-10-29 devnull break;
2331 5cdb1798 2005-10-29 devnull }
2332 5cdb1798 2005-10-29 devnull }
2333 5cdb1798 2005-10-29 devnull
2334 5cdb1798 2005-10-29 devnull Message*
2335 5cdb1798 2005-10-29 devnull bangcmd(Cmd *c, Message *m)
2336 5cdb1798 2005-10-29 devnull {
2337 5cdb1798 2005-10-29 devnull char cmd[4*1024];
2338 5cdb1798 2005-10-29 devnull char *p, *e;
2339 5cdb1798 2005-10-29 devnull char *av[4];
2340 5cdb1798 2005-10-29 devnull int i;
2341 5cdb1798 2005-10-29 devnull
2342 5cdb1798 2005-10-29 devnull cmd[0] = 0;
2343 5cdb1798 2005-10-29 devnull p = cmd;
2344 5cdb1798 2005-10-29 devnull e = cmd+sizeof(cmd);
2345 5cdb1798 2005-10-29 devnull for(i = 1; i < c->an; i++)
2346 5cdb1798 2005-10-29 devnull p = seprint(p, e, "%s ", c->av[i]);
2347 5cdb1798 2005-10-29 devnull av[0] = "rc";
2348 5cdb1798 2005-10-29 devnull av[1] = "-c";
2349 5cdb1798 2005-10-29 devnull av[2] = cmd;
2350 5cdb1798 2005-10-29 devnull av[3] = 0;
2351 7e61af51 2006-02-12 devnull system("rc", av, -1);
2352 5cdb1798 2005-10-29 devnull Bprint(&out, "!\n");
2353 5cdb1798 2005-10-29 devnull return m;
2354 5cdb1798 2005-10-29 devnull }
2355 5cdb1798 2005-10-29 devnull
2356 5cdb1798 2005-10-29 devnull Message*
2357 5cdb1798 2005-10-29 devnull xpipecmd(Cmd *c, Message *m, char *part)
2358 5cdb1798 2005-10-29 devnull {
2359 5cdb1798 2005-10-29 devnull char cmd[128];
2360 5cdb1798 2005-10-29 devnull char *p, *e;
2361 5cdb1798 2005-10-29 devnull char *av[4];
2362 5cdb1798 2005-10-29 devnull String *path;
2363 7e61af51 2006-02-12 devnull int i, fd;
2364 5cdb1798 2005-10-29 devnull
2365 5cdb1798 2005-10-29 devnull if(c->an < 2){
2366 5cdb1798 2005-10-29 devnull Bprint(&out, "!usage: | cmd\n");
2367 5cdb1798 2005-10-29 devnull return nil;
2368 5cdb1798 2005-10-29 devnull }
2369 5cdb1798 2005-10-29 devnull
2370 5cdb1798 2005-10-29 devnull if(m == &top){
2371 5cdb1798 2005-10-29 devnull Bprint(&out, "!address\n");
2372 5cdb1798 2005-10-29 devnull return nil;
2373 5cdb1798 2005-10-29 devnull }
2374 5cdb1798 2005-10-29 devnull
2375 5cdb1798 2005-10-29 devnull path = extendpath(m->path, part);
2376 7e61af51 2006-02-12 devnull fd = fsopenfd(mailfs, s_to_c(path), OREAD);
2377 5cdb1798 2005-10-29 devnull s_free(path);
2378 d4baecd9 2006-02-26 devnull
2379 cbeb0b26 2006-04-01 devnull if(fd < 0){ /* compatibility with older upas/fs */
2380 5cdb1798 2005-10-29 devnull path = extendpath(m->path, "raw");
2381 7e61af51 2006-02-12 devnull fd = fsopenfd(mailfs, s_to_c(path), OREAD);
2382 5cdb1798 2005-10-29 devnull s_free(path);
2383 5cdb1798 2005-10-29 devnull }
2384 7e61af51 2006-02-12 devnull if(fd < 0){
2385 5cdb1798 2005-10-29 devnull fprint(2, "!message disappeared\n");
2386 5cdb1798 2005-10-29 devnull return nil;
2387 5cdb1798 2005-10-29 devnull }
2388 5cdb1798 2005-10-29 devnull
2389 5cdb1798 2005-10-29 devnull p = cmd;
2390 5cdb1798 2005-10-29 devnull e = cmd+sizeof(cmd);
2391 5cdb1798 2005-10-29 devnull cmd[0] = 0;
2392 5cdb1798 2005-10-29 devnull for(i = 1; i < c->an; i++)
2393 5cdb1798 2005-10-29 devnull p = seprint(p, e, "%s ", c->av[i]);
2394 5cdb1798 2005-10-29 devnull av[0] = "rc";
2395 5cdb1798 2005-10-29 devnull av[1] = "-c";
2396 5cdb1798 2005-10-29 devnull av[2] = cmd;
2397 5cdb1798 2005-10-29 devnull av[3] = 0;
2398 7e61af51 2006-02-12 devnull system("rc", av, fd); /* system closes fd */
2399 5cdb1798 2005-10-29 devnull Bprint(&out, "!\n");
2400 5cdb1798 2005-10-29 devnull return m;
2401 5cdb1798 2005-10-29 devnull }
2402 5cdb1798 2005-10-29 devnull
2403 5cdb1798 2005-10-29 devnull Message*
2404 5cdb1798 2005-10-29 devnull pipecmd(Cmd *c, Message *m)
2405 5cdb1798 2005-10-29 devnull {
2406 5cdb1798 2005-10-29 devnull return xpipecmd(c, m, "body");
2407 5cdb1798 2005-10-29 devnull }
2408 5cdb1798 2005-10-29 devnull
2409 5cdb1798 2005-10-29 devnull Message*
2410 5cdb1798 2005-10-29 devnull rpipecmd(Cmd *c, Message *m)
2411 5cdb1798 2005-10-29 devnull {
2412 5cdb1798 2005-10-29 devnull return xpipecmd(c, m, "rawunix");
2413 5cdb1798 2005-10-29 devnull }
2414 5cdb1798 2005-10-29 devnull
2415 5cdb1798 2005-10-29 devnull void
2416 5cdb1798 2005-10-29 devnull closemb(void)
2417 5cdb1798 2005-10-29 devnull {
2418 7e61af51 2006-02-12 devnull CFid *fd;
2419 5cdb1798 2005-10-29 devnull
2420 7e61af51 2006-02-12 devnull fd = fsopen(mailfs, "ctl", OWRITE);
2421 7e61af51 2006-02-12 devnull if(fd == nil)
2422 7e61af51 2006-02-12 devnull sysfatal("can't open ctl: %r");
2423 5cdb1798 2005-10-29 devnull
2424 cbeb0b26 2006-04-01 devnull /* close current mailbox */
2425 5cdb1798 2005-10-29 devnull if(*mbname && strcmp(mbname, "mbox") != 0)
2426 7e61af51 2006-02-12 devnull fsprint(fd, "close %s", mbname);
2427 5cdb1798 2005-10-29 devnull
2428 7e61af51 2006-02-12 devnull fsclose(fd);
2429 5cdb1798 2005-10-29 devnull }
2430 5cdb1798 2005-10-29 devnull
2431 5cdb1798 2005-10-29 devnull int
2432 5cdb1798 2005-10-29 devnull switchmb(char *file, char *singleton)
2433 5cdb1798 2005-10-29 devnull {
2434 5cdb1798 2005-10-29 devnull char *p;
2435 5cdb1798 2005-10-29 devnull int n, fd;
2436 5cdb1798 2005-10-29 devnull String *path;
2437 5cdb1798 2005-10-29 devnull char buf[256];
2438 5cdb1798 2005-10-29 devnull
2439 cbeb0b26 2006-04-01 devnull /* if the user didn't say anything and there */
2440 cbeb0b26 2006-04-01 devnull /* is an mbox mounted already, use that one */
2441 cbeb0b26 2006-04-01 devnull /* so that the upas/fs -fdefault default is honored. */
2442 d4baecd9 2006-02-26 devnull if(0 && (file || (singleton && fsaccess(mailfs, singleton, 0) < 0))){
2443 7e61af51 2006-02-12 devnull /* XXX all wrong */
2444 7e61af51 2006-02-12 devnull fprint(2, "file=%s singleton=%s\n", file, singleton);
2445 5cdb1798 2005-10-29 devnull if(file == nil)
2446 5cdb1798 2005-10-29 devnull file = "mbox";
2447 5cdb1798 2005-10-29 devnull
2448 cbeb0b26 2006-04-01 devnull /* close current mailbox */
2449 5cdb1798 2005-10-29 devnull closemb();
2450 5cdb1798 2005-10-29 devnull didopen = 1;
2451 5cdb1798 2005-10-29 devnull
2452 5cdb1798 2005-10-29 devnull fd = open("/mail/fs/ctl", ORDWR);
2453 5cdb1798 2005-10-29 devnull if(fd < 0)
2454 5cdb1798 2005-10-29 devnull sysfatal("can't open /mail/fs/ctl: %r");
2455 5cdb1798 2005-10-29 devnull
2456 5cdb1798 2005-10-29 devnull path = s_new();
2457 5cdb1798 2005-10-29 devnull
2458 cbeb0b26 2006-04-01 devnull /* get an absolute path to the mail box */
2459 5cdb1798 2005-10-29 devnull if(strncmp(file, "./", 2) == 0){
2460 cbeb0b26 2006-04-01 devnull /* resolve path here since upas/fs doesn't know */
2461 cbeb0b26 2006-04-01 devnull /* our working directory */
2462 5cdb1798 2005-10-29 devnull if(getwd(buf, sizeof(buf)-strlen(file)) == nil){
2463 5cdb1798 2005-10-29 devnull fprint(2, "!can't get working directory: %s\n", buf);
2464 5cdb1798 2005-10-29 devnull return -1;
2465 5cdb1798 2005-10-29 devnull }
2466 5cdb1798 2005-10-29 devnull s_append(path, buf);
2467 5cdb1798 2005-10-29 devnull s_append(path, file+1);
2468 5cdb1798 2005-10-29 devnull } else {
2469 5cdb1798 2005-10-29 devnull mboxpath(file, user, path, 0);
2470 5cdb1798 2005-10-29 devnull }
2471 5cdb1798 2005-10-29 devnull
2472 cbeb0b26 2006-04-01 devnull /* make up a handle to use when talking to fs */
2473 5cdb1798 2005-10-29 devnull p = strrchr(file, '/');
2474 5cdb1798 2005-10-29 devnull if(p == nil){
2475 cbeb0b26 2006-04-01 devnull /* if its in the mailbox directory, just use the name */
2476 5cdb1798 2005-10-29 devnull strncpy(mbname, file, sizeof(mbname));
2477 5cdb1798 2005-10-29 devnull mbname[sizeof(mbname)-1] = 0;
2478 5cdb1798 2005-10-29 devnull } else {
2479 cbeb0b26 2006-04-01 devnull /* make up a mailbox name */
2480 5cdb1798 2005-10-29 devnull p = strrchr(s_to_c(path), '/');
2481 5cdb1798 2005-10-29 devnull p++;
2482 5cdb1798 2005-10-29 devnull if(*p == 0){
2483 5cdb1798 2005-10-29 devnull fprint(2, "!bad mbox name");
2484 5cdb1798 2005-10-29 devnull return -1;
2485 5cdb1798 2005-10-29 devnull }
2486 5cdb1798 2005-10-29 devnull strncpy(mbname, p, sizeof(mbname));
2487 5cdb1798 2005-10-29 devnull mbname[sizeof(mbname)-1] = 0;
2488 5cdb1798 2005-10-29 devnull n = strlen(mbname);
2489 5cdb1798 2005-10-29 devnull if(n > Elemlen-12)
2490 5cdb1798 2005-10-29 devnull n = Elemlen-12;
2491 5cdb1798 2005-10-29 devnull sprint(mbname+n, "%ld", time(0));
2492 5cdb1798 2005-10-29 devnull }
2493 5cdb1798 2005-10-29 devnull
2494 5cdb1798 2005-10-29 devnull if(fprint(fd, "open %s %s", s_to_c(path), mbname) < 0){
2495 5cdb1798 2005-10-29 devnull fprint(2, "!can't 'open %s %s': %r\n", file, mbname);
2496 5cdb1798 2005-10-29 devnull s_free(path);
2497 5cdb1798 2005-10-29 devnull return -1;
2498 5cdb1798 2005-10-29 devnull }
2499 5cdb1798 2005-10-29 devnull close(fd);
2500 5cdb1798 2005-10-29 devnull }else
2501 7e61af51 2006-02-12 devnull if (singleton && fsaccess(mailfs, singleton, 0)==0){
2502 7e61af51 2006-02-12 devnull if ((p = strchr(singleton, '/')) == nil){
2503 5cdb1798 2005-10-29 devnull fprint(2, "!bad mbox name");
2504 5cdb1798 2005-10-29 devnull return -1;
2505 5cdb1798 2005-10-29 devnull }
2506 7e61af51 2006-02-12 devnull n = p-singleton;
2507 7e61af51 2006-02-12 devnull strncpy(mbname, singleton, n);
2508 5cdb1798 2005-10-29 devnull mbname[n+1] = 0;
2509 5cdb1798 2005-10-29 devnull path = s_reset(nil);
2510 5cdb1798 2005-10-29 devnull mboxpath(mbname, user, path, 0);
2511 5cdb1798 2005-10-29 devnull }else{
2512 d4baecd9 2006-02-26 devnull if(file)
2513 d4baecd9 2006-02-26 devnull strecpy(mbname, mbname+sizeof mbname, file);
2514 d4baecd9 2006-02-26 devnull else
2515 d4baecd9 2006-02-26 devnull strcpy(mbname, "mbox");
2516 5cdb1798 2005-10-29 devnull path = s_reset(nil);
2517 d4baecd9 2006-02-26 devnull mboxpath(mbname, user, path, 0);
2518 5cdb1798 2005-10-29 devnull }
2519 5cdb1798 2005-10-29 devnull
2520 7e61af51 2006-02-12 devnull snprint(root, sizeof root, "%s", mbname);
2521 5cdb1798 2005-10-29 devnull rootlen = strlen(root);
2522 5cdb1798 2005-10-29 devnull
2523 5cdb1798 2005-10-29 devnull if(mbpath != nil)
2524 5cdb1798 2005-10-29 devnull s_free(mbpath);
2525 5cdb1798 2005-10-29 devnull mbpath = path;
2526 5cdb1798 2005-10-29 devnull return 0;
2527 5cdb1798 2005-10-29 devnull }
2528 5cdb1798 2005-10-29 devnull
2529 cbeb0b26 2006-04-01 devnull /* like tokenize but for into lines */
2530 5cdb1798 2005-10-29 devnull int
2531 5cdb1798 2005-10-29 devnull lineize(char *s, char **f, int n)
2532 5cdb1798 2005-10-29 devnull {
2533 5cdb1798 2005-10-29 devnull int i;
2534 5cdb1798 2005-10-29 devnull
2535 5cdb1798 2005-10-29 devnull for(i = 0; *s && i < n; i++){
2536 5cdb1798 2005-10-29 devnull f[i] = s;
2537 5cdb1798 2005-10-29 devnull s = strchr(s, '\n');
2538 5cdb1798 2005-10-29 devnull if(s == nil)
2539 5cdb1798 2005-10-29 devnull break;
2540 5cdb1798 2005-10-29 devnull *s++ = 0;
2541 5cdb1798 2005-10-29 devnull }
2542 5cdb1798 2005-10-29 devnull return i;
2543 5cdb1798 2005-10-29 devnull }
2544 5cdb1798 2005-10-29 devnull
2545 5cdb1798 2005-10-29 devnull
2546 5cdb1798 2005-10-29 devnull
2547 5cdb1798 2005-10-29 devnull String*
2548 5cdb1798 2005-10-29 devnull rooted(String *s)
2549 5cdb1798 2005-10-29 devnull {
2550 5cdb1798 2005-10-29 devnull static char buf[256];
2551 5cdb1798 2005-10-29 devnull
2552 5cdb1798 2005-10-29 devnull if(strcmp(root, ".") != 0)
2553 5cdb1798 2005-10-29 devnull return s;
2554 5cdb1798 2005-10-29 devnull snprint(buf, sizeof(buf), "/mail/fs/%s/%s", mbname, s_to_c(s));
2555 5cdb1798 2005-10-29 devnull s_free(s);
2556 5cdb1798 2005-10-29 devnull return s_copy(buf);
2557 5cdb1798 2005-10-29 devnull }
2558 5cdb1798 2005-10-29 devnull
2559 5cdb1798 2005-10-29 devnull int
2560 5cdb1798 2005-10-29 devnull plumb(Message *m, Ctype *cp)
2561 5cdb1798 2005-10-29 devnull {
2562 5cdb1798 2005-10-29 devnull String *s;
2563 5cdb1798 2005-10-29 devnull Plumbmsg *pm;
2564 5cdb1798 2005-10-29 devnull static int fd = -2;
2565 5cdb1798 2005-10-29 devnull
2566 5cdb1798 2005-10-29 devnull if(cp->plumbdest == nil)
2567 5cdb1798 2005-10-29 devnull return -1;
2568 5cdb1798 2005-10-29 devnull
2569 5cdb1798 2005-10-29 devnull if(fd < -1)
2570 5cdb1798 2005-10-29 devnull fd = plumbopen("send", OWRITE);
2571 5cdb1798 2005-10-29 devnull if(fd < 0)
2572 5cdb1798 2005-10-29 devnull return -1;
2573 5cdb1798 2005-10-29 devnull
2574 5cdb1798 2005-10-29 devnull pm = mallocz(sizeof(Plumbmsg), 1);
2575 5cdb1798 2005-10-29 devnull pm->src = strdup("mail");
2576 5cdb1798 2005-10-29 devnull if(*cp->plumbdest)
2577 5cdb1798 2005-10-29 devnull pm->dst = strdup(cp->plumbdest);
2578 5cdb1798 2005-10-29 devnull pm->wdir = nil;
2579 5cdb1798 2005-10-29 devnull pm->type = strdup("text");
2580 5cdb1798 2005-10-29 devnull pm->ndata = -1;
2581 5cdb1798 2005-10-29 devnull s = rooted(extendpath(m->path, "body"));
2582 5cdb1798 2005-10-29 devnull if(cp->ext != nil){
2583 5cdb1798 2005-10-29 devnull s_append(s, ".");
2584 5cdb1798 2005-10-29 devnull s_append(s, cp->ext);
2585 5cdb1798 2005-10-29 devnull }
2586 5cdb1798 2005-10-29 devnull pm->data = strdup(s_to_c(s));
2587 5cdb1798 2005-10-29 devnull s_free(s);
2588 5cdb1798 2005-10-29 devnull plumbsend(fd, pm);
2589 5cdb1798 2005-10-29 devnull plumbfree(pm);
2590 5cdb1798 2005-10-29 devnull return 0;
2591 5cdb1798 2005-10-29 devnull }
2592 5cdb1798 2005-10-29 devnull
2593 5cdb1798 2005-10-29 devnull void
2594 7e61af51 2006-02-12 devnull regerror(char *x)
2595 5cdb1798 2005-10-29 devnull {
2596 7e61af51 2006-02-12 devnull USED(x);
2597 5cdb1798 2005-10-29 devnull }
2598 5cdb1798 2005-10-29 devnull
2599 5cdb1798 2005-10-29 devnull String*
2600 5cdb1798 2005-10-29 devnull addrecolon(char *s)
2601 5cdb1798 2005-10-29 devnull {
2602 5cdb1798 2005-10-29 devnull String *str;
2603 5cdb1798 2005-10-29 devnull
2604 5cdb1798 2005-10-29 devnull if(cistrncmp(s, "re:", 3) != 0){
2605 5cdb1798 2005-10-29 devnull str = s_copy("Re: ");
2606 5cdb1798 2005-10-29 devnull s_append(str, s);
2607 5cdb1798 2005-10-29 devnull } else
2608 5cdb1798 2005-10-29 devnull str = s_copy(s);
2609 5cdb1798 2005-10-29 devnull return str;
2610 5cdb1798 2005-10-29 devnull }
2611 5cdb1798 2005-10-29 devnull
2612 5cdb1798 2005-10-29 devnull void
2613 5cdb1798 2005-10-29 devnull exitfs(char *rv)
2614 5cdb1798 2005-10-29 devnull {
2615 7e61af51 2006-02-12 devnull threadexitsall(rv);
2616 5cdb1798 2005-10-29 devnull }