Blame


1 9f1fdc12 2005-10-29 devnull #include <u.h>
2 9f1fdc12 2005-10-29 devnull #include <libc.h>
3 9f1fdc12 2005-10-29 devnull #include <bio.h>
4 9f1fdc12 2005-10-29 devnull #include <thread.h>
5 00d75e0e 2006-02-11 devnull #include <9pclient.h>
6 9f1fdc12 2005-10-29 devnull #include <plumb.h>
7 9f1fdc12 2005-10-29 devnull #include <ctype.h>
8 9f1fdc12 2005-10-29 devnull #include "dat.h"
9 9f1fdc12 2005-10-29 devnull
10 00d75e0e 2006-02-11 devnull char *maildir = "Mail/"; /* mountpoint of mail file system */
11 00d75e0e 2006-02-11 devnull char *mboxname = "mbox"; /* mailboxdir/mboxname is mail spool file */
12 9f1fdc12 2005-10-29 devnull char *mailboxdir = nil; /* nil == /mail/box/$user */
13 9f1fdc12 2005-10-29 devnull char *fsname; /* filesystem for mailboxdir/mboxname is at maildir/fsname */
14 9f1fdc12 2005-10-29 devnull char *user;
15 9f1fdc12 2005-10-29 devnull char *outgoing;
16 dfbaaaa6 2006-05-27 devnull char *srvname;
17 9f1fdc12 2005-10-29 devnull
18 9f1fdc12 2005-10-29 devnull Window *wbox;
19 9f1fdc12 2005-10-29 devnull Message mbox;
20 9f1fdc12 2005-10-29 devnull Message replies;
21 9f1fdc12 2005-10-29 devnull char *home;
22 00d75e0e 2006-02-11 devnull CFid *plumbsendfd;
23 00d75e0e 2006-02-11 devnull CFid *plumbseemailfd;
24 00d75e0e 2006-02-11 devnull CFid *plumbshowmailfd;
25 00d75e0e 2006-02-11 devnull CFid *plumbsendmailfd;
26 9f1fdc12 2005-10-29 devnull Channel *cplumb;
27 9f1fdc12 2005-10-29 devnull Channel *cplumbshow;
28 9f1fdc12 2005-10-29 devnull Channel *cplumbsend;
29 9f1fdc12 2005-10-29 devnull int wctlfd;
30 9f1fdc12 2005-10-29 devnull void mainctl(void*);
31 9f1fdc12 2005-10-29 devnull void plumbproc(void*);
32 9f1fdc12 2005-10-29 devnull void plumbshowproc(void*);
33 9f1fdc12 2005-10-29 devnull void plumbsendproc(void*);
34 9f1fdc12 2005-10-29 devnull void plumbthread(void);
35 9f1fdc12 2005-10-29 devnull void plumbshowthread(void*);
36 9f1fdc12 2005-10-29 devnull void plumbsendthread(void*);
37 9f1fdc12 2005-10-29 devnull
38 9f1fdc12 2005-10-29 devnull int shortmenu;
39 9f1fdc12 2005-10-29 devnull
40 3f8c36d6 2006-02-09 devnull CFsys *mailfs;
41 3f8c36d6 2006-02-09 devnull CFsys *acmefs;
42 9f1fdc12 2005-10-29 devnull
43 9f1fdc12 2005-10-29 devnull void
44 9f1fdc12 2005-10-29 devnull usage(void)
45 9f1fdc12 2005-10-29 devnull {
46 44fc56d8 2006-05-21 devnull fprint(2, "usage: Mail [-sS] [-n srvname] [-o outgoing] [mailboxname [directoryname]]\n");
47 9f1fdc12 2005-10-29 devnull threadexitsall("usage");
48 9f1fdc12 2005-10-29 devnull }
49 9f1fdc12 2005-10-29 devnull
50 9f1fdc12 2005-10-29 devnull void
51 9f1fdc12 2005-10-29 devnull removeupasfs(void)
52 9f1fdc12 2005-10-29 devnull {
53 9f1fdc12 2005-10-29 devnull char buf[256];
54 9f1fdc12 2005-10-29 devnull
55 9f1fdc12 2005-10-29 devnull if(strcmp(mboxname, "mbox") == 0)
56 9f1fdc12 2005-10-29 devnull return;
57 9f1fdc12 2005-10-29 devnull snprint(buf, sizeof buf, "close %s", mboxname);
58 3f8c36d6 2006-02-09 devnull fswrite(mbox.ctlfd, buf, strlen(buf));
59 9f1fdc12 2005-10-29 devnull }
60 9f1fdc12 2005-10-29 devnull
61 9f1fdc12 2005-10-29 devnull int
62 9f1fdc12 2005-10-29 devnull ismaildir(char *s)
63 9f1fdc12 2005-10-29 devnull {
64 9f1fdc12 2005-10-29 devnull Dir *d;
65 9f1fdc12 2005-10-29 devnull int ret;
66 9f1fdc12 2005-10-29 devnull
67 3b5862ee 2006-02-14 devnull d = fsdirstat(mailfs, s);
68 9f1fdc12 2005-10-29 devnull if(d == nil)
69 9f1fdc12 2005-10-29 devnull return 0;
70 9f1fdc12 2005-10-29 devnull ret = d->qid.type & QTDIR;
71 9f1fdc12 2005-10-29 devnull free(d);
72 9f1fdc12 2005-10-29 devnull return ret;
73 9f1fdc12 2005-10-29 devnull }
74 9f1fdc12 2005-10-29 devnull
75 9f1fdc12 2005-10-29 devnull void
76 9f1fdc12 2005-10-29 devnull threadmain(int argc, char *argv[])
77 9f1fdc12 2005-10-29 devnull {
78 dfbaaaa6 2006-05-27 devnull char *s, *name;
79 9f1fdc12 2005-10-29 devnull char err[ERRMAX], *cmd;
80 9f1fdc12 2005-10-29 devnull int i, newdir;
81 9f1fdc12 2005-10-29 devnull Fmt fmt;
82 9f1fdc12 2005-10-29 devnull
83 9f1fdc12 2005-10-29 devnull doquote = needsrcquote;
84 9f1fdc12 2005-10-29 devnull quotefmtinstall();
85 9f1fdc12 2005-10-29 devnull
86 9f1fdc12 2005-10-29 devnull /* open these early so we won't miss notification of new mail messages while we read mbox */
87 7b5db1c3 2009-09-12 lejatorn if((plumbsendfd = plumbopenfid("send", OWRITE|OCEXEC)) == nil)
88 7b5db1c3 2009-09-12 lejatorn fprint(2, "warning: open plumb/send: %r\n");
89 7b5db1c3 2009-09-12 lejatorn if((plumbseemailfd = plumbopenfid("seemail", OREAD|OCEXEC)) == nil)
90 7b5db1c3 2009-09-12 lejatorn fprint(2, "warning: open plumb/seemail: %r\n");
91 7b5db1c3 2009-09-12 lejatorn if((plumbshowmailfd = plumbopenfid("showmail", OREAD|OCEXEC)) == nil)
92 7b5db1c3 2009-09-12 lejatorn fprint(2, "warning: open plumb/showmail: %r\n");
93 9f1fdc12 2005-10-29 devnull
94 9f1fdc12 2005-10-29 devnull shortmenu = 0;
95 44fc56d8 2006-05-21 devnull srvname = "mail";
96 9f1fdc12 2005-10-29 devnull ARGBEGIN{
97 9f1fdc12 2005-10-29 devnull case 's':
98 9f1fdc12 2005-10-29 devnull shortmenu = 1;
99 9f1fdc12 2005-10-29 devnull break;
100 9f1fdc12 2005-10-29 devnull case 'S':
101 9f1fdc12 2005-10-29 devnull shortmenu = 2;
102 9f1fdc12 2005-10-29 devnull break;
103 9f1fdc12 2005-10-29 devnull case 'o':
104 9f1fdc12 2005-10-29 devnull outgoing = EARGF(usage());
105 9f1fdc12 2005-10-29 devnull break;
106 9f1fdc12 2005-10-29 devnull case 'm':
107 9f1fdc12 2005-10-29 devnull smprint(maildir, "%s/", EARGF(usage()));
108 44fc56d8 2006-05-21 devnull break;
109 44fc56d8 2006-05-21 devnull case 'n':
110 44fc56d8 2006-05-21 devnull srvname = EARGF(usage());
111 9f1fdc12 2005-10-29 devnull break;
112 9f1fdc12 2005-10-29 devnull default:
113 9f1fdc12 2005-10-29 devnull usage();
114 9f1fdc12 2005-10-29 devnull }ARGEND
115 9f1fdc12 2005-10-29 devnull
116 3f8c36d6 2006-02-09 devnull acmefs = nsmount("acme",nil);
117 3f8c36d6 2006-02-09 devnull if(acmefs == nil)
118 3f8c36d6 2006-02-09 devnull error("cannot mount acme: %r");
119 44fc56d8 2006-05-21 devnull mailfs = nsmount(srvname, nil);
120 3f8c36d6 2006-02-09 devnull if(mailfs == nil)
121 44fc56d8 2006-05-21 devnull error("cannot mount %s: %r", srvname);
122 9f1fdc12 2005-10-29 devnull
123 00d75e0e 2006-02-11 devnull name = "mbox";
124 9f1fdc12 2005-10-29 devnull
125 9f1fdc12 2005-10-29 devnull newdir = 1;
126 9f1fdc12 2005-10-29 devnull if(argc > 0){
127 9f1fdc12 2005-10-29 devnull i = strlen(argv[0]);
128 9f1fdc12 2005-10-29 devnull if(argc>2 || i==0)
129 9f1fdc12 2005-10-29 devnull usage();
130 9f1fdc12 2005-10-29 devnull /* see if the name is that of an existing /mail/fs directory */
131 3b5862ee 2006-02-14 devnull if(argc==1 && argv[0][0] != '/' && ismaildir(argv[0])){
132 9f1fdc12 2005-10-29 devnull name = argv[0];
133 3b5862ee 2006-02-14 devnull mboxname = estrdup(name);
134 9f1fdc12 2005-10-29 devnull newdir = 0;
135 9f1fdc12 2005-10-29 devnull }else{
136 9f1fdc12 2005-10-29 devnull if(argv[0][i-1] == '/')
137 9f1fdc12 2005-10-29 devnull argv[0][i-1] = '\0';
138 9f1fdc12 2005-10-29 devnull s = strrchr(argv[0], '/');
139 9f1fdc12 2005-10-29 devnull if(s == nil)
140 9f1fdc12 2005-10-29 devnull mboxname = estrdup(argv[0]);
141 9f1fdc12 2005-10-29 devnull else{
142 9f1fdc12 2005-10-29 devnull *s++ = '\0';
143 9f1fdc12 2005-10-29 devnull if(*s == '\0')
144 9f1fdc12 2005-10-29 devnull usage();
145 9f1fdc12 2005-10-29 devnull mailboxdir = argv[0];
146 9f1fdc12 2005-10-29 devnull mboxname = estrdup(s);
147 9f1fdc12 2005-10-29 devnull }
148 9f1fdc12 2005-10-29 devnull if(argc > 1)
149 9f1fdc12 2005-10-29 devnull name = argv[1];
150 9f1fdc12 2005-10-29 devnull else
151 9f1fdc12 2005-10-29 devnull name = mboxname;
152 9f1fdc12 2005-10-29 devnull }
153 9f1fdc12 2005-10-29 devnull }
154 9f1fdc12 2005-10-29 devnull
155 9f1fdc12 2005-10-29 devnull user = getenv("user");
156 9f1fdc12 2005-10-29 devnull if(user == nil)
157 9f1fdc12 2005-10-29 devnull user = "none";
158 3f8c36d6 2006-02-09 devnull home = getenv("home");
159 3f8c36d6 2006-02-09 devnull if(home == nil)
160 3f8c36d6 2006-02-09 devnull home = getenv("HOME");
161 3f8c36d6 2006-02-09 devnull if(home == nil)
162 3f8c36d6 2006-02-09 devnull error("can't find $home");
163 9f1fdc12 2005-10-29 devnull if(mailboxdir == nil)
164 3f8c36d6 2006-02-09 devnull mailboxdir = estrstrdup(home, "/mail");
165 9f1fdc12 2005-10-29 devnull if(outgoing == nil)
166 9f1fdc12 2005-10-29 devnull outgoing = estrstrdup(mailboxdir, "/outgoing");
167 9f1fdc12 2005-10-29 devnull
168 3b5862ee 2006-02-14 devnull mbox.ctlfd = fsopen(mailfs, estrstrdup(mboxname, "/ctl"), OWRITE);
169 3f8c36d6 2006-02-09 devnull if(mbox.ctlfd == nil)
170 3b5862ee 2006-02-14 devnull error("can't open %s: %r", estrstrdup(mboxname, "/ctl"));
171 9f1fdc12 2005-10-29 devnull
172 9f1fdc12 2005-10-29 devnull fsname = estrdup(name);
173 9f1fdc12 2005-10-29 devnull if(newdir && argc > 0){
174 9f1fdc12 2005-10-29 devnull s = emalloc(5+strlen(mailboxdir)+strlen(mboxname)+strlen(name)+10+1);
175 9f1fdc12 2005-10-29 devnull for(i=0; i<10; i++){
176 9f1fdc12 2005-10-29 devnull sprint(s, "open %s/%s %s", mailboxdir, mboxname, fsname);
177 3f8c36d6 2006-02-09 devnull if(fswrite(mbox.ctlfd, s, strlen(s)) >= 0)
178 9f1fdc12 2005-10-29 devnull break;
179 9f1fdc12 2005-10-29 devnull err[0] = '\0';
180 9f1fdc12 2005-10-29 devnull errstr(err, sizeof err);
181 9f1fdc12 2005-10-29 devnull if(strstr(err, "mbox name in use") == nil)
182 3f8c36d6 2006-02-09 devnull error("can't create directory %s for mail: %s", name, err);
183 9f1fdc12 2005-10-29 devnull free(fsname);
184 9f1fdc12 2005-10-29 devnull fsname = emalloc(strlen(name)+10);
185 9f1fdc12 2005-10-29 devnull sprint(fsname, "%s-%d", name, i);
186 9f1fdc12 2005-10-29 devnull }
187 9f1fdc12 2005-10-29 devnull if(i == 10)
188 9f1fdc12 2005-10-29 devnull error("can't open %s/%s: %r", mailboxdir, mboxname);
189 9f1fdc12 2005-10-29 devnull free(s);
190 9f1fdc12 2005-10-29 devnull }
191 9f1fdc12 2005-10-29 devnull
192 9f1fdc12 2005-10-29 devnull s = estrstrdup(fsname, "/");
193 9f1fdc12 2005-10-29 devnull mbox.name = estrstrdup(maildir, s);
194 9f1fdc12 2005-10-29 devnull mbox.level= 0;
195 9f1fdc12 2005-10-29 devnull readmbox(&mbox, maildir, s);
196 9f1fdc12 2005-10-29 devnull home = getenv("home");
197 9f1fdc12 2005-10-29 devnull if(home == nil)
198 9f1fdc12 2005-10-29 devnull home = "/";
199 9f1fdc12 2005-10-29 devnull
200 9f1fdc12 2005-10-29 devnull wbox = newwindow();
201 9f1fdc12 2005-10-29 devnull winname(wbox, mbox.name);
202 9f1fdc12 2005-10-29 devnull wintagwrite(wbox, "Put Mail Delmesg ", 3+1+4+1+7+1);
203 9f1fdc12 2005-10-29 devnull threadcreate(mainctl, wbox, STACK);
204 9f1fdc12 2005-10-29 devnull
205 9f1fdc12 2005-10-29 devnull fmtstrinit(&fmt);
206 9f1fdc12 2005-10-29 devnull fmtprint(&fmt, "Mail");
207 9f1fdc12 2005-10-29 devnull if(shortmenu)
208 9f1fdc12 2005-10-29 devnull fmtprint(&fmt, " -%c", "sS"[shortmenu-1]);
209 9f1fdc12 2005-10-29 devnull if(outgoing)
210 9f1fdc12 2005-10-29 devnull fmtprint(&fmt, " -o %s", outgoing);
211 9f1fdc12 2005-10-29 devnull fmtprint(&fmt, " %s", name);
212 9f1fdc12 2005-10-29 devnull cmd = fmtstrflush(&fmt);
213 9f1fdc12 2005-10-29 devnull if(cmd == nil)
214 9f1fdc12 2005-10-29 devnull sysfatal("out of memory");
215 9f1fdc12 2005-10-29 devnull winsetdump(wbox, "/acme/mail", cmd);
216 9f1fdc12 2005-10-29 devnull mbox.w = wbox;
217 9f1fdc12 2005-10-29 devnull
218 9f1fdc12 2005-10-29 devnull mesgmenu(wbox, &mbox);
219 9f1fdc12 2005-10-29 devnull winclean(wbox);
220 9f1fdc12 2005-10-29 devnull
221 3f8c36d6 2006-02-09 devnull /* wctlfd = open("/dev/wctl", OWRITE|OCEXEC); /* for acme window */
222 3f8c36d6 2006-02-09 devnull wctlfd = -1;
223 9f1fdc12 2005-10-29 devnull cplumb = chancreate(sizeof(Plumbmsg*), 0);
224 9f1fdc12 2005-10-29 devnull cplumbshow = chancreate(sizeof(Plumbmsg*), 0);
225 00d75e0e 2006-02-11 devnull if(strcmp(name, "mbox") == 0){
226 9f1fdc12 2005-10-29 devnull /*
227 9f1fdc12 2005-10-29 devnull * Avoid creating multiple windows to send mail by only accepting
228 9f1fdc12 2005-10-29 devnull * sendmail plumb messages if we're reading the main mailbox.
229 9f1fdc12 2005-10-29 devnull */
230 00d75e0e 2006-02-11 devnull plumbsendmailfd = plumbopenfid("sendmail", OREAD|OCEXEC);
231 9f1fdc12 2005-10-29 devnull cplumbsend = chancreate(sizeof(Plumbmsg*), 0);
232 9f1fdc12 2005-10-29 devnull proccreate(plumbsendproc, nil, STACK);
233 9f1fdc12 2005-10-29 devnull threadcreate(plumbsendthread, nil, STACK);
234 9f1fdc12 2005-10-29 devnull }
235 9f1fdc12 2005-10-29 devnull /* start plumb reader as separate proc ... */
236 9f1fdc12 2005-10-29 devnull proccreate(plumbproc, nil, STACK);
237 9f1fdc12 2005-10-29 devnull proccreate(plumbshowproc, nil, STACK);
238 9f1fdc12 2005-10-29 devnull threadcreate(plumbshowthread, nil, STACK);
239 7cc0e47f 2007-06-23 devnull fswrite(mbox.ctlfd, "refresh", 7);
240 9f1fdc12 2005-10-29 devnull /* ... and use this thread to read the messages */
241 9f1fdc12 2005-10-29 devnull plumbthread();
242 9f1fdc12 2005-10-29 devnull }
243 9f1fdc12 2005-10-29 devnull
244 9f1fdc12 2005-10-29 devnull void
245 9f1fdc12 2005-10-29 devnull plumbproc(void* v)
246 9f1fdc12 2005-10-29 devnull {
247 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
248 9f1fdc12 2005-10-29 devnull
249 9f1fdc12 2005-10-29 devnull threadsetname("plumbproc");
250 9f1fdc12 2005-10-29 devnull for(;;){
251 00d75e0e 2006-02-11 devnull m = plumbrecvfid(plumbseemailfd);
252 9f1fdc12 2005-10-29 devnull sendp(cplumb, m);
253 9f1fdc12 2005-10-29 devnull if(m == nil)
254 9f1fdc12 2005-10-29 devnull threadexits(nil);
255 9f1fdc12 2005-10-29 devnull }
256 9f1fdc12 2005-10-29 devnull }
257 9f1fdc12 2005-10-29 devnull
258 9f1fdc12 2005-10-29 devnull void
259 9f1fdc12 2005-10-29 devnull plumbshowproc(void* v)
260 9f1fdc12 2005-10-29 devnull {
261 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
262 9f1fdc12 2005-10-29 devnull
263 9f1fdc12 2005-10-29 devnull threadsetname("plumbshowproc");
264 9f1fdc12 2005-10-29 devnull for(;;){
265 00d75e0e 2006-02-11 devnull m = plumbrecvfid(plumbshowmailfd);
266 9f1fdc12 2005-10-29 devnull sendp(cplumbshow, m);
267 9f1fdc12 2005-10-29 devnull if(m == nil)
268 9f1fdc12 2005-10-29 devnull threadexits(nil);
269 9f1fdc12 2005-10-29 devnull }
270 9f1fdc12 2005-10-29 devnull }
271 9f1fdc12 2005-10-29 devnull
272 9f1fdc12 2005-10-29 devnull void
273 9f1fdc12 2005-10-29 devnull plumbsendproc(void* v)
274 9f1fdc12 2005-10-29 devnull {
275 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
276 9f1fdc12 2005-10-29 devnull
277 9f1fdc12 2005-10-29 devnull threadsetname("plumbsendproc");
278 9f1fdc12 2005-10-29 devnull for(;;){
279 00d75e0e 2006-02-11 devnull m = plumbrecvfid(plumbsendmailfd);
280 9f1fdc12 2005-10-29 devnull sendp(cplumbsend, m);
281 9f1fdc12 2005-10-29 devnull if(m == nil)
282 9f1fdc12 2005-10-29 devnull threadexits(nil);
283 9f1fdc12 2005-10-29 devnull }
284 9f1fdc12 2005-10-29 devnull }
285 9f1fdc12 2005-10-29 devnull
286 9f1fdc12 2005-10-29 devnull void
287 9f1fdc12 2005-10-29 devnull newmesg(char *name, char *digest)
288 9f1fdc12 2005-10-29 devnull {
289 9f1fdc12 2005-10-29 devnull Dir *d;
290 9f1fdc12 2005-10-29 devnull
291 3f8c36d6 2006-02-09 devnull if(strncmp(name, mbox.name, strlen(mbox.name)) != 0)
292 9f1fdc12 2005-10-29 devnull return; /* message is about another mailbox */
293 3f8c36d6 2006-02-09 devnull if(mesglookupfile(&mbox, name, digest) != nil)
294 9f1fdc12 2005-10-29 devnull return;
295 00d75e0e 2006-02-11 devnull if(strncmp(name, "Mail/", 5) == 0)
296 00d75e0e 2006-02-11 devnull name += 5;
297 3f8c36d6 2006-02-09 devnull d = fsdirstat(mailfs, name);
298 3f8c36d6 2006-02-09 devnull if(d == nil)
299 9f1fdc12 2005-10-29 devnull return;
300 3f8c36d6 2006-02-09 devnull if(mesgadd(&mbox, mbox.name, d, digest))
301 9f1fdc12 2005-10-29 devnull mesgmenunew(wbox, &mbox);
302 9f1fdc12 2005-10-29 devnull free(d);
303 9f1fdc12 2005-10-29 devnull }
304 9f1fdc12 2005-10-29 devnull
305 9f1fdc12 2005-10-29 devnull void
306 9f1fdc12 2005-10-29 devnull showmesg(char *name, char *digest)
307 9f1fdc12 2005-10-29 devnull {
308 9f1fdc12 2005-10-29 devnull char *n;
309 3f8c36d6 2006-02-09 devnull char *mb;
310 00d75e0e 2006-02-11 devnull
311 3f8c36d6 2006-02-09 devnull mb = mbox.name;
312 3f8c36d6 2006-02-09 devnull if(strncmp(name, mb, strlen(mb)) != 0)
313 9f1fdc12 2005-10-29 devnull return; /* message is about another mailbox */
314 3f8c36d6 2006-02-09 devnull n = estrdup(name+strlen(mb));
315 9f1fdc12 2005-10-29 devnull if(n[strlen(n)-1] != '/')
316 9f1fdc12 2005-10-29 devnull n = egrow(n, "/", nil);
317 3f8c36d6 2006-02-09 devnull mesgopen(&mbox, mbox.name, name+strlen(mb), nil, 1, digest);
318 9f1fdc12 2005-10-29 devnull free(n);
319 9f1fdc12 2005-10-29 devnull }
320 9f1fdc12 2005-10-29 devnull
321 9f1fdc12 2005-10-29 devnull void
322 0d42cc9d 2006-02-28 devnull delmesg(char *name, char *digest, int dodel, char *save)
323 9f1fdc12 2005-10-29 devnull {
324 9f1fdc12 2005-10-29 devnull Message *m;
325 9f1fdc12 2005-10-29 devnull
326 9f1fdc12 2005-10-29 devnull m = mesglookupfile(&mbox, name, digest);
327 9f1fdc12 2005-10-29 devnull if(m != nil){
328 0d42cc9d 2006-02-28 devnull if(save)
329 0d42cc9d 2006-02-28 devnull mesgcommand(m, estrstrdup("Save ", save));
330 9f1fdc12 2005-10-29 devnull if(dodel)
331 0d42cc9d 2006-02-28 devnull mesgmenumarkdel(wbox, &mbox, m, 1);
332 0d42cc9d 2006-02-28 devnull else{
333 0d42cc9d 2006-02-28 devnull /* notification came from plumber - message is gone */
334 0d42cc9d 2006-02-28 devnull mesgmenudel(wbox, &mbox, m);
335 0d42cc9d 2006-02-28 devnull if(!m->opened)
336 0d42cc9d 2006-02-28 devnull mesgdel(&mbox, m);
337 0d42cc9d 2006-02-28 devnull }
338 9f1fdc12 2005-10-29 devnull }
339 9f1fdc12 2005-10-29 devnull }
340 9f1fdc12 2005-10-29 devnull
341 9f1fdc12 2005-10-29 devnull void
342 9f1fdc12 2005-10-29 devnull plumbthread(void)
343 9f1fdc12 2005-10-29 devnull {
344 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
345 9f1fdc12 2005-10-29 devnull Plumbattr *a;
346 9f1fdc12 2005-10-29 devnull char *type, *digest;
347 9f1fdc12 2005-10-29 devnull
348 9f1fdc12 2005-10-29 devnull threadsetname("plumbthread");
349 9f1fdc12 2005-10-29 devnull while((m = recvp(cplumb)) != nil){
350 9f1fdc12 2005-10-29 devnull a = m->attr;
351 9f1fdc12 2005-10-29 devnull digest = plumblookup(a, "digest");
352 9f1fdc12 2005-10-29 devnull type = plumblookup(a, "mailtype");
353 9f1fdc12 2005-10-29 devnull if(type == nil)
354 9f1fdc12 2005-10-29 devnull fprint(2, "Mail: plumb message with no mailtype attribute\n");
355 9f1fdc12 2005-10-29 devnull else if(strcmp(type, "new") == 0)
356 9f1fdc12 2005-10-29 devnull newmesg(m->data, digest);
357 9f1fdc12 2005-10-29 devnull else if(strcmp(type, "delete") == 0)
358 0d42cc9d 2006-02-28 devnull delmesg(m->data, digest, 0, nil);
359 9f1fdc12 2005-10-29 devnull else
360 9f1fdc12 2005-10-29 devnull fprint(2, "Mail: unknown plumb attribute %s\n", type);
361 9f1fdc12 2005-10-29 devnull plumbfree(m);
362 9f1fdc12 2005-10-29 devnull }
363 9f1fdc12 2005-10-29 devnull threadexits(nil);
364 9f1fdc12 2005-10-29 devnull }
365 9f1fdc12 2005-10-29 devnull
366 9f1fdc12 2005-10-29 devnull void
367 3f8c36d6 2006-02-09 devnull plumbshowthread(void *v)
368 9f1fdc12 2005-10-29 devnull {
369 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
370 9f1fdc12 2005-10-29 devnull
371 3f8c36d6 2006-02-09 devnull USED(v);
372 9f1fdc12 2005-10-29 devnull threadsetname("plumbshowthread");
373 9f1fdc12 2005-10-29 devnull while((m = recvp(cplumbshow)) != nil){
374 9f1fdc12 2005-10-29 devnull showmesg(m->data, plumblookup(m->attr, "digest"));
375 9f1fdc12 2005-10-29 devnull plumbfree(m);
376 9f1fdc12 2005-10-29 devnull }
377 9f1fdc12 2005-10-29 devnull threadexits(nil);
378 9f1fdc12 2005-10-29 devnull }
379 9f1fdc12 2005-10-29 devnull
380 9f1fdc12 2005-10-29 devnull void
381 3f8c36d6 2006-02-09 devnull plumbsendthread(void *v)
382 9f1fdc12 2005-10-29 devnull {
383 9f1fdc12 2005-10-29 devnull Plumbmsg *m;
384 9f1fdc12 2005-10-29 devnull
385 3f8c36d6 2006-02-09 devnull USED(v);
386 9f1fdc12 2005-10-29 devnull threadsetname("plumbsendthread");
387 9f1fdc12 2005-10-29 devnull while((m = recvp(cplumbsend)) != nil){
388 9f1fdc12 2005-10-29 devnull mkreply(nil, "Mail", m->data, m->attr, nil);
389 9f1fdc12 2005-10-29 devnull plumbfree(m);
390 9f1fdc12 2005-10-29 devnull }
391 9f1fdc12 2005-10-29 devnull threadexits(nil);
392 9f1fdc12 2005-10-29 devnull }
393 9f1fdc12 2005-10-29 devnull
394 9f1fdc12 2005-10-29 devnull int
395 9f1fdc12 2005-10-29 devnull mboxcommand(Window *w, char *s)
396 9f1fdc12 2005-10-29 devnull {
397 0d42cc9d 2006-02-28 devnull char *args[10], **targs, *save;
398 7603066e 2013-09-06 rsc Window *sbox;
399 9f1fdc12 2005-10-29 devnull Message *m, *next;
400 9f1fdc12 2005-10-29 devnull int ok, nargs, i, j;
401 7603066e 2013-09-06 rsc CFid *searchfd;
402 7603066e 2013-09-06 rsc char buf[128], *res;
403 9f1fdc12 2005-10-29 devnull
404 9f1fdc12 2005-10-29 devnull nargs = tokenize(s, args, nelem(args));
405 9f1fdc12 2005-10-29 devnull if(nargs == 0)
406 9f1fdc12 2005-10-29 devnull return 0;
407 9f1fdc12 2005-10-29 devnull if(strcmp(args[0], "Mail") == 0){
408 9f1fdc12 2005-10-29 devnull if(nargs == 1)
409 9f1fdc12 2005-10-29 devnull mkreply(nil, "Mail", "", nil, nil);
410 9f1fdc12 2005-10-29 devnull else
411 9f1fdc12 2005-10-29 devnull mkreply(nil, "Mail", args[1], nil, nil);
412 9f1fdc12 2005-10-29 devnull return 1;
413 9f1fdc12 2005-10-29 devnull }
414 9f1fdc12 2005-10-29 devnull if(strcmp(s, "Del") == 0){
415 9f1fdc12 2005-10-29 devnull if(mbox.dirty){
416 9f1fdc12 2005-10-29 devnull mbox.dirty = 0;
417 9f1fdc12 2005-10-29 devnull fprint(2, "mail: mailbox not written\n");
418 9f1fdc12 2005-10-29 devnull return 1;
419 9f1fdc12 2005-10-29 devnull }
420 7603066e 2013-09-06 rsc if(w != mbox.w){
421 7603066e 2013-09-06 rsc windel(w, 1);
422 7603066e 2013-09-06 rsc return 1;
423 7603066e 2013-09-06 rsc }
424 9f1fdc12 2005-10-29 devnull ok = 1;
425 9f1fdc12 2005-10-29 devnull for(m=mbox.head; m!=nil; m=next){
426 9f1fdc12 2005-10-29 devnull next = m->next;
427 9f1fdc12 2005-10-29 devnull if(m->w){
428 9f1fdc12 2005-10-29 devnull if(windel(m->w, 0))
429 9f1fdc12 2005-10-29 devnull m->w = nil;
430 9f1fdc12 2005-10-29 devnull else
431 9f1fdc12 2005-10-29 devnull ok = 0;
432 9f1fdc12 2005-10-29 devnull }
433 9f1fdc12 2005-10-29 devnull }
434 9f1fdc12 2005-10-29 devnull for(m=replies.head; m!=nil; m=next){
435 9f1fdc12 2005-10-29 devnull next = m->next;
436 9f1fdc12 2005-10-29 devnull if(m->w){
437 9f1fdc12 2005-10-29 devnull if(windel(m->w, 0))
438 9f1fdc12 2005-10-29 devnull m->w = nil;
439 9f1fdc12 2005-10-29 devnull else
440 9f1fdc12 2005-10-29 devnull ok = 0;
441 9f1fdc12 2005-10-29 devnull }
442 9f1fdc12 2005-10-29 devnull }
443 9f1fdc12 2005-10-29 devnull if(ok){
444 9f1fdc12 2005-10-29 devnull windel(w, 1);
445 9f1fdc12 2005-10-29 devnull removeupasfs();
446 9f1fdc12 2005-10-29 devnull threadexitsall(nil);
447 9f1fdc12 2005-10-29 devnull }
448 9f1fdc12 2005-10-29 devnull return 1;
449 9f1fdc12 2005-10-29 devnull }
450 9f1fdc12 2005-10-29 devnull if(strcmp(s, "Put") == 0){
451 9f1fdc12 2005-10-29 devnull rewritembox(wbox, &mbox);
452 7cc0e47f 2007-06-23 devnull return 1;
453 7cc0e47f 2007-06-23 devnull }
454 7cc0e47f 2007-06-23 devnull if(strcmp(s, "Get") == 0){
455 7cc0e47f 2007-06-23 devnull fswrite(mbox.ctlfd, "refresh", 7);
456 9f1fdc12 2005-10-29 devnull return 1;
457 9f1fdc12 2005-10-29 devnull }
458 9f1fdc12 2005-10-29 devnull if(strcmp(s, "Delmesg") == 0){
459 0d42cc9d 2006-02-28 devnull save = nil;
460 0d42cc9d 2006-02-28 devnull if(nargs > 1)
461 0d42cc9d 2006-02-28 devnull save = args[1];
462 9f1fdc12 2005-10-29 devnull s = winselection(w);
463 9f1fdc12 2005-10-29 devnull if(s == nil)
464 9f1fdc12 2005-10-29 devnull return 1;
465 9f1fdc12 2005-10-29 devnull nargs = 1;
466 9f1fdc12 2005-10-29 devnull for(i=0; s[i]; i++)
467 9f1fdc12 2005-10-29 devnull if(s[i] == '\n')
468 9f1fdc12 2005-10-29 devnull nargs++;
469 9f1fdc12 2005-10-29 devnull targs = emalloc(nargs*sizeof(char*)); /* could be too many for a local array */
470 9f1fdc12 2005-10-29 devnull nargs = getfields(s, targs, nargs, 1, "\n");
471 9f1fdc12 2005-10-29 devnull for(i=0; i<nargs; i++){
472 9f1fdc12 2005-10-29 devnull if(!isdigit(targs[i][0]))
473 9f1fdc12 2005-10-29 devnull continue;
474 9f1fdc12 2005-10-29 devnull j = atoi(targs[i]); /* easy way to parse the number! */
475 9f1fdc12 2005-10-29 devnull if(j == 0)
476 9f1fdc12 2005-10-29 devnull continue;
477 9f1fdc12 2005-10-29 devnull snprint(buf, sizeof buf, "%s%d", mbox.name, j);
478 0d42cc9d 2006-02-28 devnull delmesg(buf, nil, 1, save);
479 9f1fdc12 2005-10-29 devnull }
480 9f1fdc12 2005-10-29 devnull free(s);
481 9f1fdc12 2005-10-29 devnull free(targs);
482 9f1fdc12 2005-10-29 devnull return 1;
483 9f1fdc12 2005-10-29 devnull }
484 7603066e 2013-09-06 rsc if(strcmp(s, "Search") == 0){
485 7603066e 2013-09-06 rsc if(nargs <= 1)
486 7603066e 2013-09-06 rsc return 1;
487 7603066e 2013-09-06 rsc s = estrstrdup(mboxname, "/search");
488 7603066e 2013-09-06 rsc searchfd = fsopen(mailfs, s, ORDWR);
489 7603066e 2013-09-06 rsc if(searchfd == nil)
490 7603066e 2013-09-06 rsc return 1;
491 7603066e 2013-09-06 rsc save = estrdup(args[1]);
492 7603066e 2013-09-06 rsc for(i=2; i<nargs; i++)
493 7603066e 2013-09-06 rsc save = eappend(save, " ", args[i]);
494 7603066e 2013-09-06 rsc fswrite(searchfd, save, strlen(save));
495 7603066e 2013-09-06 rsc fsseek(searchfd, 0, 0);
496 7603066e 2013-09-06 rsc j = fsread(searchfd, buf, sizeof buf - 1);
497 7603066e 2013-09-06 rsc if(j == 0){
498 7603066e 2013-09-06 rsc fprint(2, "[%s] search %s: no results found\n", mboxname, save);
499 7603066e 2013-09-06 rsc fsclose(searchfd);
500 7603066e 2013-09-06 rsc free(save);
501 7603066e 2013-09-06 rsc return 1;
502 7603066e 2013-09-06 rsc }
503 7603066e 2013-09-06 rsc free(save);
504 7603066e 2013-09-06 rsc buf[j] = '\0';
505 7603066e 2013-09-06 rsc res = estrdup(buf);
506 7603066e 2013-09-06 rsc j = fsread(searchfd, buf, sizeof buf - 1);
507 7603066e 2013-09-06 rsc for(; j != 0; j = fsread(searchfd, buf, sizeof buf - 1), buf[j] = '\0')
508 7603066e 2013-09-06 rsc res = eappend(res, "", buf);
509 7603066e 2013-09-06 rsc fsclose(searchfd);
510 7603066e 2013-09-06 rsc
511 7603066e 2013-09-06 rsc sbox = newwindow();
512 7603066e 2013-09-06 rsc winname(sbox, s);
513 7603066e 2013-09-06 rsc free(s);
514 7603066e 2013-09-06 rsc threadcreate(mainctl, sbox, STACK);
515 7603066e 2013-09-06 rsc winopenbody(sbox, OWRITE);
516 7603066e 2013-09-06 rsc
517 7603066e 2013-09-06 rsc /* show results in reverse order */
518 7603066e 2013-09-06 rsc m = mbox.tail;
519 7603066e 2013-09-06 rsc save = nil;
520 7603066e 2013-09-06 rsc for(s=strrchr(res, ' '); s!=nil || save!=res; s=strrchr(res, ' ')){
521 7603066e 2013-09-06 rsc if(s != nil){
522 7603066e 2013-09-06 rsc save = s+1;
523 7603066e 2013-09-06 rsc *s = '\0';
524 7603066e 2013-09-06 rsc }
525 7603066e 2013-09-06 rsc else save = res;
526 7603066e 2013-09-06 rsc save = estrstrdup(save, "/");
527 7603066e 2013-09-06 rsc for(; m && strcmp(save, m->name) != 0; m=m->prev);
528 7603066e 2013-09-06 rsc free(save);
529 7603066e 2013-09-06 rsc if(m == nil)
530 7603066e 2013-09-06 rsc break;
531 7603066e 2013-09-06 rsc fsprint(sbox->body, "%s%s\n", m->name, info(m, 0, 0));
532 7603066e 2013-09-06 rsc m = m->prev;
533 7603066e 2013-09-06 rsc }
534 7603066e 2013-09-06 rsc free(res);
535 7603066e 2013-09-06 rsc winclean(sbox);
536 7603066e 2013-09-06 rsc winclosebody(sbox);
537 7603066e 2013-09-06 rsc return 1;
538 7603066e 2013-09-06 rsc }
539 9f1fdc12 2005-10-29 devnull return 0;
540 9f1fdc12 2005-10-29 devnull }
541 9f1fdc12 2005-10-29 devnull
542 9f1fdc12 2005-10-29 devnull void
543 9f1fdc12 2005-10-29 devnull mainctl(void *v)
544 9f1fdc12 2005-10-29 devnull {
545 9f1fdc12 2005-10-29 devnull Window *w;
546 9f1fdc12 2005-10-29 devnull Event *e, *e2, *eq, *ea;
547 9f1fdc12 2005-10-29 devnull int na, nopen;
548 9f1fdc12 2005-10-29 devnull char *s, *t, *buf;
549 9f1fdc12 2005-10-29 devnull
550 9f1fdc12 2005-10-29 devnull w = v;
551 880ab2f1 2006-02-15 devnull winincref(w);
552 9f1fdc12 2005-10-29 devnull proccreate(wineventproc, w, STACK);
553 9f1fdc12 2005-10-29 devnull
554 9f1fdc12 2005-10-29 devnull for(;;){
555 9f1fdc12 2005-10-29 devnull e = recvp(w->cevent);
556 9f1fdc12 2005-10-29 devnull switch(e->c1){
557 9f1fdc12 2005-10-29 devnull default:
558 9f1fdc12 2005-10-29 devnull Unknown:
559 9f1fdc12 2005-10-29 devnull print("unknown message %c%c\n", e->c1, e->c2);
560 9f1fdc12 2005-10-29 devnull break;
561 fa325e9b 2020-01-10 cross
562 9f1fdc12 2005-10-29 devnull case 'E': /* write to body; can't affect us */
563 9f1fdc12 2005-10-29 devnull break;
564 fa325e9b 2020-01-10 cross
565 9f1fdc12 2005-10-29 devnull case 'F': /* generated by our actions; ignore */
566 9f1fdc12 2005-10-29 devnull break;
567 fa325e9b 2020-01-10 cross
568 9f1fdc12 2005-10-29 devnull case 'K': /* type away; we don't care */
569 9f1fdc12 2005-10-29 devnull break;
570 fa325e9b 2020-01-10 cross
571 9f1fdc12 2005-10-29 devnull case 'M':
572 9f1fdc12 2005-10-29 devnull switch(e->c2){
573 9f1fdc12 2005-10-29 devnull case 'x':
574 9f1fdc12 2005-10-29 devnull case 'X':
575 9f1fdc12 2005-10-29 devnull ea = nil;
576 9f1fdc12 2005-10-29 devnull e2 = nil;
577 9f1fdc12 2005-10-29 devnull if(e->flag & 2)
578 9f1fdc12 2005-10-29 devnull e2 = recvp(w->cevent);
579 9f1fdc12 2005-10-29 devnull if(e->flag & 8){
580 9f1fdc12 2005-10-29 devnull ea = recvp(w->cevent);
581 9f1fdc12 2005-10-29 devnull na = ea->nb;
582 9f1fdc12 2005-10-29 devnull recvp(w->cevent);
583 9f1fdc12 2005-10-29 devnull }else
584 9f1fdc12 2005-10-29 devnull na = 0;
585 9f1fdc12 2005-10-29 devnull s = e->b;
586 9f1fdc12 2005-10-29 devnull /* if it's a known command, do it */
587 9f1fdc12 2005-10-29 devnull if((e->flag&2) && e->nb==0)
588 9f1fdc12 2005-10-29 devnull s = e2->b;
589 9f1fdc12 2005-10-29 devnull if(na){
590 9f1fdc12 2005-10-29 devnull t = emalloc(strlen(s)+1+na+1);
591 9f1fdc12 2005-10-29 devnull sprint(t, "%s %s", s, ea->b);
592 9f1fdc12 2005-10-29 devnull s = t;
593 9f1fdc12 2005-10-29 devnull }
594 9f1fdc12 2005-10-29 devnull /* if it's a long message, it can't be for us anyway */
595 9f1fdc12 2005-10-29 devnull if(!mboxcommand(w, s)) /* send it back */
596 9f1fdc12 2005-10-29 devnull winwriteevent(w, e);
597 9f1fdc12 2005-10-29 devnull if(na)
598 9f1fdc12 2005-10-29 devnull free(s);
599 9f1fdc12 2005-10-29 devnull break;
600 fa325e9b 2020-01-10 cross
601 9f1fdc12 2005-10-29 devnull case 'l':
602 9f1fdc12 2005-10-29 devnull case 'L':
603 9f1fdc12 2005-10-29 devnull buf = nil;
604 9f1fdc12 2005-10-29 devnull eq = e;
605 9f1fdc12 2005-10-29 devnull if(e->flag & 2){
606 9f1fdc12 2005-10-29 devnull e2 = recvp(w->cevent);
607 9f1fdc12 2005-10-29 devnull eq = e2;
608 9f1fdc12 2005-10-29 devnull }
609 9f1fdc12 2005-10-29 devnull s = eq->b;
610 9f1fdc12 2005-10-29 devnull if(eq->q1>eq->q0 && eq->nb==0){
611 9f1fdc12 2005-10-29 devnull buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
612 9f1fdc12 2005-10-29 devnull winread(w, eq->q0, eq->q1, buf);
613 9f1fdc12 2005-10-29 devnull s = buf;
614 9f1fdc12 2005-10-29 devnull }
615 9f1fdc12 2005-10-29 devnull nopen = 0;
616 9f1fdc12 2005-10-29 devnull do{
617 9f1fdc12 2005-10-29 devnull /* skip 'deleted' string if present' */
618 9f1fdc12 2005-10-29 devnull if(strncmp(s, deleted, strlen(deleted)) == 0)
619 9f1fdc12 2005-10-29 devnull s += strlen(deleted);
620 9f1fdc12 2005-10-29 devnull /* skip mail box name if present */
621 9f1fdc12 2005-10-29 devnull if(strncmp(s, mbox.name, strlen(mbox.name)) == 0)
622 9f1fdc12 2005-10-29 devnull s += strlen(mbox.name);
623 9f1fdc12 2005-10-29 devnull nopen += mesgopen(&mbox, mbox.name, s, nil, 0, nil);
624 9f1fdc12 2005-10-29 devnull while(*s!='\0' && *s++!='\n')
625 9f1fdc12 2005-10-29 devnull ;
626 9f1fdc12 2005-10-29 devnull }while(*s);
627 9f1fdc12 2005-10-29 devnull if(nopen == 0) /* send it back */
628 9f1fdc12 2005-10-29 devnull winwriteevent(w, e);
629 9f1fdc12 2005-10-29 devnull free(buf);
630 9f1fdc12 2005-10-29 devnull break;
631 fa325e9b 2020-01-10 cross
632 9f1fdc12 2005-10-29 devnull case 'I': /* modify away; we don't care */
633 9f1fdc12 2005-10-29 devnull case 'D':
634 9f1fdc12 2005-10-29 devnull case 'd':
635 9f1fdc12 2005-10-29 devnull case 'i':
636 9f1fdc12 2005-10-29 devnull break;
637 fa325e9b 2020-01-10 cross
638 9f1fdc12 2005-10-29 devnull default:
639 9f1fdc12 2005-10-29 devnull goto Unknown;
640 9f1fdc12 2005-10-29 devnull }
641 9f1fdc12 2005-10-29 devnull }
642 9f1fdc12 2005-10-29 devnull }
643 9f1fdc12 2005-10-29 devnull }