rev |
line source |
yuuji@0
|
1 /* ========================================================================
|
yuuji@0
|
2 * Copyright 1988-2008 University of Washington
|
yuuji@0
|
3 *
|
yuuji@0
|
4 * Licensed under the Apache License, Version 2.0 (the "License");
|
yuuji@0
|
5 * you may not use this file except in compliance with the License.
|
yuuji@0
|
6 * You may obtain a copy of the License at
|
yuuji@0
|
7 *
|
yuuji@0
|
8 * http://www.apache.org/licenses/LICENSE-2.0
|
yuuji@0
|
9 *
|
yuuji@0
|
10 *
|
yuuji@0
|
11 * ========================================================================
|
yuuji@0
|
12 */
|
yuuji@0
|
13
|
yuuji@0
|
14 /*
|
yuuji@0
|
15 * Program: Mail utility
|
yuuji@0
|
16 *
|
yuuji@0
|
17 * Author: Mark Crispin
|
yuuji@0
|
18 * UW Technology
|
yuuji@0
|
19 * University of Washington
|
yuuji@0
|
20 * Seattle, WA 98195
|
yuuji@0
|
21 * Internet: MRC@Washington.EDU
|
yuuji@0
|
22 *
|
yuuji@0
|
23 * Date: 2 February 1994
|
yuuji@0
|
24 * Last Edited: 19 February 2008
|
yuuji@0
|
25 */
|
yuuji@0
|
26
|
yuuji@0
|
27
|
yuuji@0
|
28 #include <stdio.h>
|
yuuji@0
|
29 #include <errno.h>
|
yuuji@0
|
30 extern int errno; /* just in case */
|
yuuji@0
|
31 #include "c-client.h"
|
yuuji@0
|
32 #ifdef SYSCONFIG /* defined in env_unix.h */
|
yuuji@0
|
33 #include <pwd.h>
|
yuuji@0
|
34 #endif
|
yuuji@0
|
35
|
yuuji@0
|
36 /* Globals */
|
yuuji@0
|
37
|
yuuji@0
|
38 char *version = "13"; /* edit number */
|
yuuji@0
|
39 int debugp = NIL; /* flag saying debug */
|
yuuji@0
|
40 int verbosep = NIL; /* flag saying verbose */
|
yuuji@0
|
41 int rwcopyp = NIL; /* flag saying readwrite copy (for POP) */
|
yuuji@0
|
42 int kwcopyp = NIL; /* flag saying keyword copy */
|
yuuji@0
|
43 int ignorep = NIL; /* flag saying ignore keywords */
|
yuuji@0
|
44 int critical = NIL; /* flag saying in critical code */
|
yuuji@0
|
45 int trycreate = NIL; /* [TRYCREATE] seen */
|
yuuji@0
|
46 char *suffix = NIL; /* suffer merge mode suffix text */
|
yuuji@0
|
47 int ddelim = -1; /* destination delimiter */
|
yuuji@0
|
48 FILE *f = NIL;
|
yuuji@0
|
49
|
yuuji@0
|
50 /* Usage strings */
|
yuuji@0
|
51
|
yuuji@0
|
52 char *usage2 = "usage: %s %s\n\n%s\n";
|
yuuji@0
|
53 char *usage3 = "usage: %s %s %s\n\n%s\n";
|
yuuji@0
|
54 char *usgchk = "check [MAILBOX]";
|
yuuji@0
|
55 char *usgcre = "create MAILBOX";
|
yuuji@0
|
56 char *usgdel = "delete MAILBOX";
|
yuuji@0
|
57 char *usgren = "rename SOURCE DESTINATION";
|
yuuji@0
|
58 char *usgcpymov = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
|
yuuji@0
|
59 char *usgappdel = "[-rw[copy]] [-kw[copy]] [-ig[nore]] SOURCE DESTINATION";
|
yuuji@0
|
60 char *usgprn = "prune mailbox SEARCH_CRITERIA";
|
yuuji@0
|
61 char *usgxfr = "transfer [-rw[copy]] [-kw[copy]] [-ig[nore]] [-m[erge] m] SOURCE DEST";
|
yuuji@0
|
62 #ifdef SYSCONFIG
|
yuuji@0
|
63 char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]] [-u[ser] userid] [--]";
|
yuuji@0
|
64 #else
|
yuuji@0
|
65 char *stdsw = "Standard switches valid with any command:\n\t[-d[ebug]] [-v[erbose]]";
|
yuuji@0
|
66 #endif
|
yuuji@0
|
67
|
yuuji@0
|
68 /* Merge modes */
|
yuuji@0
|
69
|
yuuji@0
|
70 #define mPROMPT 1
|
yuuji@0
|
71 #define mAPPEND 2
|
yuuji@0
|
72 #define mSUFFIX 3
|
yuuji@0
|
73
|
yuuji@0
|
74
|
yuuji@0
|
75 /* Function prototypes */
|
yuuji@0
|
76
|
yuuji@0
|
77 void ms_init (STRING *s,void *data,unsigned long size);
|
yuuji@0
|
78 char ms_next (STRING *s);
|
yuuji@0
|
79 void ms_setpos (STRING *s,unsigned long i);
|
yuuji@0
|
80 int main (int argc,char *argv[]);
|
yuuji@0
|
81 SEARCHPGM *prune_criteria (char *criteria);
|
yuuji@0
|
82 int prune_criteria_number (unsigned long *number,char **r);
|
yuuji@0
|
83 int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
|
yuuji@0
|
84 int mode);
|
yuuji@0
|
85 long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
|
yuuji@0
|
86 STRING **message);
|
yuuji@0
|
87
|
yuuji@0
|
88
|
yuuji@0
|
89 /* Append package */
|
yuuji@0
|
90
|
yuuji@0
|
91 typedef struct append_package {
|
yuuji@0
|
92 MAILSTREAM *stream; /* source stream */
|
yuuji@0
|
93 unsigned long msgno; /* current message number */
|
yuuji@0
|
94 unsigned long msgmax; /* maximum message number */
|
yuuji@0
|
95 char *flags; /* current flags */
|
yuuji@0
|
96 char *date; /* message internal date */
|
yuuji@0
|
97 STRING *message; /* stringstruct of message */
|
yuuji@0
|
98 } APPENDPACKAGE;
|
yuuji@0
|
99
|
yuuji@0
|
100
|
yuuji@0
|
101 /* Message string driver for message stringstructs */
|
yuuji@0
|
102
|
yuuji@0
|
103 STRINGDRIVER mstring = {
|
yuuji@0
|
104 ms_init, /* initialize string structure */
|
yuuji@0
|
105 ms_next, /* get next byte in string structure */
|
yuuji@0
|
106 ms_setpos /* set position in string structure */
|
yuuji@0
|
107 };
|
yuuji@0
|
108
|
yuuji@0
|
109 /* Initialize file string structure for file stringstruct
|
yuuji@0
|
110 * Accepts: string structure
|
yuuji@0
|
111 * pointer to message data structure
|
yuuji@0
|
112 * size of string
|
yuuji@0
|
113 */
|
yuuji@0
|
114
|
yuuji@0
|
115 void ms_init (STRING *s,void *data,unsigned long size)
|
yuuji@0
|
116 {
|
yuuji@0
|
117 APPENDPACKAGE *md = (APPENDPACKAGE *) data;
|
yuuji@0
|
118 s->data = data; /* note stream/msgno and header length */
|
yuuji@0
|
119 mail_fetch_header (md->stream,md->msgno,NIL,NIL,&s->data1,
|
yuuji@0
|
120 FT_PREFETCHTEXT|FT_PEEK);
|
yuuji@0
|
121 #if 0
|
yuuji@0
|
122 s->size = size; /* message size */
|
yuuji@0
|
123 #else /* This kludge is necessary because of broken IMAP servers (sigh!) */
|
yuuji@0
|
124 mail_fetch_text (md->stream,md->msgno,NIL,&s->size,FT_PEEK);
|
yuuji@0
|
125 s->size += s->data1; /* header + body size */
|
yuuji@0
|
126 #endif
|
yuuji@0
|
127 SETPOS (s,0);
|
yuuji@0
|
128 }
|
yuuji@0
|
129
|
yuuji@0
|
130
|
yuuji@0
|
131 /* Get next character from file stringstruct
|
yuuji@0
|
132 * Accepts: string structure
|
yuuji@0
|
133 * Returns: character, string structure chunk refreshed
|
yuuji@0
|
134 */
|
yuuji@0
|
135
|
yuuji@0
|
136 char ms_next (STRING *s)
|
yuuji@0
|
137 {
|
yuuji@0
|
138 char c = *s->curpos++; /* get next byte */
|
yuuji@0
|
139 SETPOS (s,GETPOS (s)); /* move to next chunk */
|
yuuji@0
|
140 return c; /* return the byte */
|
yuuji@0
|
141 }
|
yuuji@0
|
142
|
yuuji@0
|
143
|
yuuji@0
|
144 /* Set string pointer position for file stringstruct
|
yuuji@0
|
145 * Accepts: string structure
|
yuuji@0
|
146 * new position
|
yuuji@0
|
147 */
|
yuuji@0
|
148
|
yuuji@0
|
149 void ms_setpos (STRING *s,unsigned long i)
|
yuuji@0
|
150 {
|
yuuji@0
|
151 APPENDPACKAGE *md = (APPENDPACKAGE *) s->data;
|
yuuji@0
|
152 if (i < s->data1) { /* want header? */
|
yuuji@0
|
153 s->chunk = mail_fetch_header (md->stream,md->msgno,NIL,NIL,NIL,FT_PEEK);
|
yuuji@0
|
154 s->chunksize = s->data1; /* header length */
|
yuuji@0
|
155 s->offset = 0; /* offset is start of message */
|
yuuji@0
|
156 }
|
yuuji@0
|
157 else if (i < s->size) { /* want body */
|
yuuji@0
|
158 s->chunk = mail_fetch_text (md->stream,md->msgno,NIL,NIL,FT_PEEK);
|
yuuji@0
|
159 s->chunksize = s->size - s->data1;
|
yuuji@0
|
160 s->offset = s->data1; /* offset is end of header */
|
yuuji@0
|
161 }
|
yuuji@0
|
162 else { /* off end of message */
|
yuuji@0
|
163 s->chunk = NIL; /* make sure that we crack on this then */
|
yuuji@0
|
164 s->chunksize = 1; /* make sure SNX cracks the right way... */
|
yuuji@0
|
165 s->offset = i;
|
yuuji@0
|
166 }
|
yuuji@0
|
167 /* initial position and size */
|
yuuji@0
|
168 s->curpos = s->chunk + (i -= s->offset);
|
yuuji@0
|
169 s->cursize = s->chunksize - i;
|
yuuji@0
|
170 }
|
yuuji@0
|
171
|
yuuji@0
|
172 /* Main program */
|
yuuji@0
|
173
|
yuuji@0
|
174 int main (int argc,char *argv[])
|
yuuji@0
|
175 {
|
yuuji@0
|
176 MAILSTREAM *source = NIL;
|
yuuji@0
|
177 MAILSTREAM *dest = NIL;
|
yuuji@0
|
178 SEARCHPGM *criteria;
|
yuuji@0
|
179 char c,*s,*dp,*t,*t1,tmp[MAILTMPLEN],mbx[MAILTMPLEN];
|
yuuji@0
|
180 unsigned long m,len,curlen,start,last;
|
yuuji@0
|
181 int i;
|
yuuji@0
|
182 int merge = NIL;
|
yuuji@0
|
183 int retcode = 1;
|
yuuji@0
|
184 int moreswitchp = T;
|
yuuji@0
|
185 char *cmd = NIL;
|
yuuji@0
|
186 char *src = NIL;
|
yuuji@0
|
187 char *dst = NIL;
|
yuuji@0
|
188 char *pgm = argc ? argv[0] : "mailutil";
|
yuuji@0
|
189 #include "linkage.c"
|
yuuji@0
|
190 for (i = 1; i < argc; i++) {
|
yuuji@0
|
191 s = argv[i]; /* pick up argument */
|
yuuji@0
|
192 /* parse switches */
|
yuuji@0
|
193 if (moreswitchp && (*s == '-')) {
|
yuuji@0
|
194 if (!strcmp (s,"-debug") || !strcmp (s,"-d")) debugp = T;
|
yuuji@0
|
195 else if (!strcmp (s,"-verbose") || !strcmp (s,"-v")) verbosep = T;
|
yuuji@0
|
196 else if (!strcmp (s,"-rwcopy") || !strcmp (s,"-rw")) rwcopyp = T;
|
yuuji@0
|
197 else if (!strcmp (s,"-kwcopy") || !strcmp (s,"-kw")) kwcopyp = T;
|
yuuji@0
|
198 else if (!strcmp (s,"-ignore") || !strcmp (s,"-ig")) ignorep = T;
|
yuuji@0
|
199 else if ((!strcmp (s,"-merge") || !strcmp (s,"-m")) && (++i < argc)) {
|
yuuji@0
|
200 if (!strcmp (s = argv[i],"prompt")) merge = mPROMPT;
|
yuuji@0
|
201 else if (!strcmp (s,"append")) merge = mAPPEND;
|
yuuji@0
|
202 else if (!strncmp (s,"suffix=",7) && s[7]) {
|
yuuji@0
|
203 merge = mSUFFIX;
|
yuuji@0
|
204 suffix = cpystr (s+7);
|
yuuji@0
|
205 }
|
yuuji@0
|
206 else {
|
yuuji@0
|
207 printf ("unknown merge option: %s\n",s);
|
yuuji@0
|
208 exit (retcode);
|
yuuji@0
|
209 }
|
yuuji@0
|
210 }
|
yuuji@0
|
211
|
yuuji@0
|
212 #ifdef SYSCONFIG
|
yuuji@0
|
213 else if ((!strcmp (s,"-user") || !strcmp (s,"-u")) && (++i < argc)) {
|
yuuji@0
|
214 struct passwd *pw = getpwnam (s = argv[i]);
|
yuuji@0
|
215 if (!pw) {
|
yuuji@0
|
216 printf ("unknown user id: %s\n",argv[i]);
|
yuuji@0
|
217 exit (retcode);
|
yuuji@0
|
218 }
|
yuuji@0
|
219 else if (setuid (pw->pw_uid)) {
|
yuuji@0
|
220 perror ("unable to change user id");
|
yuuji@0
|
221 exit (retcode);
|
yuuji@0
|
222 }
|
yuuji@0
|
223 }
|
yuuji@0
|
224 #endif
|
yuuji@0
|
225 /* -- means no more switches, so mailbox
|
yuuji@0
|
226 name can start with "-" */
|
yuuji@0
|
227 else if ((s[1] == '-') && !s[2]) moreswitchp = NIL;
|
yuuji@0
|
228 else {
|
yuuji@0
|
229 printf ("unknown switch: %s\n",s);
|
yuuji@0
|
230 exit (retcode);
|
yuuji@0
|
231 }
|
yuuji@0
|
232 }
|
yuuji@0
|
233 else if (!cmd) cmd = s; /* first non-switch is command */
|
yuuji@0
|
234 else if (!src) src = s; /* second non-switch is source */
|
yuuji@0
|
235 else if (!dst) dst = s; /* third non-switch is destination */
|
yuuji@0
|
236 else {
|
yuuji@0
|
237 printf ("unknown argument: %s\n",s);
|
yuuji@0
|
238 exit (retcode);
|
yuuji@0
|
239 }
|
yuuji@0
|
240 }
|
yuuji@0
|
241 if (kwcopyp && ignorep) {
|
yuuji@0
|
242 puts ("-kwcopy and -ignore are mutually exclusive");
|
yuuji@0
|
243 exit (retcode);
|
yuuji@0
|
244 }
|
yuuji@0
|
245 if (!cmd) cmd = ""; /* prevent SEGV */
|
yuuji@0
|
246
|
yuuji@0
|
247 if (!strcmp (cmd,"check")) { /* check for new messages */
|
yuuji@0
|
248 if (!src) src = "INBOX";
|
yuuji@0
|
249 if (dst || merge || rwcopyp || kwcopyp || ignorep)
|
yuuji@0
|
250 printf (usage2,pgm,usgchk,stdsw);
|
yuuji@0
|
251 else if (mail_status (source = (*src == '{') ?
|
yuuji@0
|
252 mail_open (NIL,src,OP_HALFOPEN |
|
yuuji@0
|
253 (debugp ? OP_DEBUG : NIL)) : NIL,
|
yuuji@0
|
254 src,SA_MESSAGES | SA_RECENT | SA_UNSEEN))
|
yuuji@0
|
255 retcode = 0;
|
yuuji@0
|
256 }
|
yuuji@0
|
257 else if (!strcmp (cmd,"create")) {
|
yuuji@0
|
258 if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
|
yuuji@0
|
259 printf (usage2,pgm,usgcre,stdsw);
|
yuuji@0
|
260 else if (mail_create (source = (*src == '{') ?
|
yuuji@0
|
261 mail_open (NIL,src,OP_HALFOPEN |
|
yuuji@0
|
262 (debugp ? OP_DEBUG : NIL)) : NIL,src))
|
yuuji@0
|
263 retcode = 0;
|
yuuji@0
|
264 }
|
yuuji@0
|
265 else if (!strcmp (cmd,"delete")) {
|
yuuji@0
|
266 if (!src || dst || merge || rwcopyp || kwcopyp || ignorep)
|
yuuji@0
|
267 printf (usage2,pgm,usgdel,stdsw);
|
yuuji@0
|
268 else if (mail_delete (source = (*src == '{') ?
|
yuuji@0
|
269 mail_open (NIL,src,OP_HALFOPEN |
|
yuuji@0
|
270 (debugp ? OP_DEBUG : NIL)) : NIL,src))
|
yuuji@0
|
271 retcode = 0;
|
yuuji@0
|
272 }
|
yuuji@0
|
273 else if (!strcmp (cmd,"rename")) {
|
yuuji@0
|
274 if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep)
|
yuuji@0
|
275 printf (usage2,pgm,usgren,stdsw);
|
yuuji@0
|
276 else if (mail_rename (source = (*src == '{') ?
|
yuuji@0
|
277 mail_open (NIL,src,OP_HALFOPEN |
|
yuuji@0
|
278 (debugp ? OP_DEBUG : NIL)) : NIL,src,dst))
|
yuuji@0
|
279 retcode = 0;
|
yuuji@0
|
280 }
|
yuuji@0
|
281
|
yuuji@0
|
282 else if ((i = !strcmp (cmd,"move")) || !strcmp (cmd,"copy")) {
|
yuuji@0
|
283 if (!src || !dst || merge) printf (usage3,pgm,cmd,usgcpymov,stdsw);
|
yuuji@0
|
284 else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
|
yuuji@0
|
285 (debugp ? OP_DEBUG : NIL))) {
|
yuuji@0
|
286 dest = NIL; /* open destination stream if network */
|
yuuji@0
|
287 if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
|
yuuji@0
|
288 (debugp ? OP_DEBUG : NIL)))) {
|
yuuji@0
|
289 if (mbxcopy (source,dest,dst,T,i,merge)) retcode = 0;
|
yuuji@0
|
290 }
|
yuuji@0
|
291 }
|
yuuji@0
|
292 }
|
yuuji@0
|
293 else if ((i = !strcmp (cmd,"appenddelete")) || !strcmp (cmd,"append")) {
|
yuuji@0
|
294 if (!src || !dst || merge) printf (usage3,pgm,cmd,usgappdel,stdsw);
|
yuuji@0
|
295 else if (source = mail_open (NIL,src,((i || rwcopyp) ? NIL : OP_READONLY) |
|
yuuji@0
|
296 (debugp ? OP_DEBUG : NIL))) {
|
yuuji@0
|
297 dest = NIL; /* open destination stream if network */
|
yuuji@0
|
298 if ((*dst != '{') || (dest = mail_open (NIL,dst,OP_HALFOPEN |
|
yuuji@0
|
299 (debugp ? OP_DEBUG : NIL)))) {
|
yuuji@0
|
300 if (mbxcopy (source,dest,dst,NIL,i,merge)) retcode = 0;
|
yuuji@0
|
301 }
|
yuuji@0
|
302 }
|
yuuji@0
|
303 }
|
yuuji@0
|
304
|
yuuji@0
|
305 else if (!strcmp (cmd,"prune")) {
|
yuuji@0
|
306 if (!src || !dst || merge || rwcopyp || kwcopyp || ignorep ||
|
yuuji@0
|
307 !(criteria = prune_criteria (dst))) printf (usage2,pgm,usgprn,stdsw);
|
yuuji@0
|
308 else if ((source = mail_open (NIL,src,(debugp ? OP_DEBUG : NIL))) &&
|
yuuji@0
|
309 mail_search_full (source,NIL,criteria,SE_FREE)) {
|
yuuji@0
|
310 for (m = 1, s = t = NIL, len = start = last = 0; m <= source->nmsgs; m++)
|
yuuji@0
|
311 if (mail_elt (source,m)->searched) {
|
yuuji@0
|
312 if (s) { /* continuing a range? */
|
yuuji@0
|
313 if (m == last + 1) last = m;
|
yuuji@0
|
314 else { /* no, end of previous range? */
|
yuuji@0
|
315 if (last != start) sprintf (t,":%lu,%lu",last,m);
|
yuuji@0
|
316 /* no, just this message */
|
yuuji@0
|
317 else sprintf (t,",%lu",m);
|
yuuji@0
|
318 start = last = m; /* either way, start new range */
|
yuuji@0
|
319 /* running out of space? */
|
yuuji@0
|
320 if ((len - (curlen = (t += strlen (t)) - s)) < 20) {
|
yuuji@0
|
321 fs_resize ((void **) &s,len += MAILTMPLEN);
|
yuuji@0
|
322 t = s + curlen; /* relocate current pointer */
|
yuuji@0
|
323 }
|
yuuji@0
|
324 }
|
yuuji@0
|
325 }
|
yuuji@0
|
326 else { /* first time, start new buffer */
|
yuuji@0
|
327 s = (char *) fs_get (len = MAILTMPLEN);
|
yuuji@0
|
328 sprintf (s,"%lu",start = last = m);
|
yuuji@0
|
329 t = s + strlen (s); /* end of buffer */
|
yuuji@0
|
330 }
|
yuuji@0
|
331 }
|
yuuji@0
|
332 /* finish last range if necessary */
|
yuuji@0
|
333 if (last != start) sprintf (t,":%lu",last);
|
yuuji@0
|
334 if (s) { /* delete/expunge any matching messages */
|
yuuji@0
|
335 mail_flag (source,s,"\\Deleted",ST_SET);
|
yuuji@0
|
336 m = source->nmsgs; /* get number of messages before purge */
|
yuuji@0
|
337 mail_expunge (source);
|
yuuji@0
|
338 printf ("%lu message(s) purged\n",m - source->nmsgs);
|
yuuji@0
|
339 fs_give ((void **) &s); /* flush buffer */
|
yuuji@0
|
340 }
|
yuuji@0
|
341 else puts ("No matching messages, so nothing purged");
|
yuuji@0
|
342 source = mail_close (source);
|
yuuji@0
|
343 }
|
yuuji@0
|
344 }
|
yuuji@0
|
345
|
yuuji@0
|
346 else if (!strcmp (cmd,"transfer")) {
|
yuuji@0
|
347 if (!src || !dst) printf (usage2,pgm,usgxfr,stdsw);
|
yuuji@0
|
348 else if ((*src == '{') && /* open source mailbox */
|
yuuji@0
|
349 !(source = mail_open (NIL,src,OP_HALFOPEN |
|
yuuji@0
|
350 (debugp ? OP_DEBUG : NIL))));
|
yuuji@0
|
351 else if ((*dst == '{') && /* open destination server */
|
yuuji@0
|
352 !(dest = mail_open (NIL,dst,OP_HALFOPEN |
|
yuuji@0
|
353 (debugp ? OP_DEBUG : NIL))));
|
yuuji@0
|
354 else if (!(f = tmpfile ())) puts ("can't open temporary file");
|
yuuji@0
|
355 else {
|
yuuji@0
|
356 if (verbosep) puts ("Listing mailboxes...");
|
yuuji@0
|
357 if (dest) strcpy (strchr (strcpy (tmp,dest->mailbox),'}') + 1,
|
yuuji@0
|
358 dp = strchr (dst,'}') + 1);
|
yuuji@0
|
359 else {
|
yuuji@0
|
360 dp = dst;
|
yuuji@0
|
361 tmp[0] = '\0';
|
yuuji@0
|
362 }
|
yuuji@0
|
363 mail_list (dest,tmp,"");
|
yuuji@0
|
364 rewind (f); /* list all mailboxes matching prefix */
|
yuuji@0
|
365 if (ddelim < 0) { /* if server failed to give delimiter */
|
yuuji@0
|
366 puts ("warning: unable to get destination hierarchy delimiter!");
|
yuuji@0
|
367 ddelim = 0; /* default to none */
|
yuuji@0
|
368 }
|
yuuji@0
|
369 if (source) strcpy (strchr (strcpy (tmp,source->mailbox),'}') + 1,
|
yuuji@0
|
370 strchr (src,'}') + 1);
|
yuuji@0
|
371 else strcpy (tmp,src);
|
yuuji@0
|
372 mail_list (source,tmp,"*");
|
yuuji@0
|
373 rewind (f);
|
yuuji@0
|
374 /* read back mailbox names */
|
yuuji@0
|
375 for (retcode = 0; !retcode && (fgets (tmp,MAILTMPLEN-1,f)); ) {
|
yuuji@0
|
376 if (t = strchr (tmp+1,'\n')) *t = '\0';
|
yuuji@0
|
377 for (t = mbx,t1 = dest ? dest->mailbox : "",c = NIL; (c != '}') && *t1;
|
yuuji@0
|
378 *t++ = c= *t1++);
|
yuuji@0
|
379 for (t1 = dp; *t1; *t++ = *t1++);
|
yuuji@0
|
380 /* point to name without delim or netspec */
|
yuuji@0
|
381 t1 = source ? (strchr (tmp+1,'}') + 1) : tmp + 1;
|
yuuji@0
|
382 /* src and mbx have different delimiters? */
|
yuuji@0
|
383 if (ddelim && (ddelim != tmp[0]))
|
yuuji@0
|
384 while (c = *t1++) { /* swap delimiters then */
|
yuuji@0
|
385 if (c == ddelim) c = tmp[0] ? tmp[0] : 'x';
|
yuuji@0
|
386 else if (c == tmp[0]) c = ddelim;
|
yuuji@0
|
387 *t++ = c;
|
yuuji@0
|
388 }
|
yuuji@0
|
389 /* easy case */
|
yuuji@0
|
390 else while (*t1) *t++ = *t1++;
|
yuuji@0
|
391 *t++ = '\0';
|
yuuji@0
|
392 if (verbosep) {
|
yuuji@0
|
393 printf ("Copying %s\n => %s\n",tmp+1,mbx);
|
yuuji@0
|
394 fflush (stdout);
|
yuuji@0
|
395 }
|
yuuji@0
|
396 if (source = mail_open (source,tmp+1,(debugp ? OP_DEBUG : NIL) |
|
yuuji@0
|
397 (rwcopyp ? NIL : OP_READONLY))) {
|
yuuji@0
|
398 if (!mbxcopy (source,dest,mbx,T,NIL,merge)) retcode = 1;
|
yuuji@0
|
399 if (source->dtb->flags & DR_LOCAL) source = mail_close (source);
|
yuuji@0
|
400 }
|
yuuji@0
|
401 else printf ("can't open source mailbox %s\n",tmp+1);
|
yuuji@0
|
402 }
|
yuuji@0
|
403 }
|
yuuji@0
|
404 }
|
yuuji@0
|
405
|
yuuji@0
|
406 else {
|
yuuji@0
|
407 printf ("%s version %s.%s\n\n",pgm,CCLIENTVERSION,version);
|
yuuji@0
|
408 printf (usage2,pgm,"command [switches] arguments",stdsw);
|
yuuji@0
|
409 printf ("\nCommands:\n %s\n",usgchk);
|
yuuji@0
|
410 puts (" ;; report number of messages and new messages");
|
yuuji@0
|
411 printf (" %s\n",usgcre);
|
yuuji@0
|
412 puts (" ;; create new mailbox");
|
yuuji@0
|
413 printf (" %s\n",usgdel);
|
yuuji@0
|
414 puts (" ;; delete existing mailbox");
|
yuuji@0
|
415 printf (" %s\n",usgren);
|
yuuji@0
|
416 puts (" ;; rename mailbox to a new name");
|
yuuji@0
|
417 printf (" copy %s\n",usgcpymov);
|
yuuji@0
|
418 printf (" move %s\n",usgcpymov);
|
yuuji@0
|
419 puts (" ;; create new mailbox and copy/move messages");
|
yuuji@0
|
420 printf (" append %s\n",usgappdel);
|
yuuji@0
|
421 printf (" appenddelete %s\n",usgappdel);
|
yuuji@0
|
422 puts (" ;; copy/move messages to existing mailbox");
|
yuuji@0
|
423 printf (" %s\n",usgprn);
|
yuuji@0
|
424 puts (" ;; prune mailbox of messages matching criteria");
|
yuuji@0
|
425 printf (" %s\n",usgxfr);
|
yuuji@0
|
426 puts (" ;; copy source hierarchy to destination");
|
yuuji@0
|
427 puts (" ;; -merge modes are prompt, append, or suffix=xxxx");
|
yuuji@0
|
428 }
|
yuuji@0
|
429 /* close streams */
|
yuuji@0
|
430 if (source) mail_close (source);
|
yuuji@0
|
431 if (dest) mail_close (dest);
|
yuuji@0
|
432 exit (retcode);
|
yuuji@0
|
433 return retcode; /* stupid compilers */
|
yuuji@0
|
434 }
|
yuuji@0
|
435
|
yuuji@0
|
436 /* Pruning criteria, somewhat extended from mail_criteria()
|
yuuji@0
|
437 * Accepts: criteria
|
yuuji@0
|
438 * Returns: search program if parse successful, else NIL
|
yuuji@0
|
439 */
|
yuuji@0
|
440
|
yuuji@0
|
441 SEARCHPGM *prune_criteria (char *criteria)
|
yuuji@0
|
442 {
|
yuuji@0
|
443 SEARCHPGM *pgm = NIL;
|
yuuji@0
|
444 char *criterion,*r,tmp[MAILTMPLEN];
|
yuuji@0
|
445 int f;
|
yuuji@0
|
446 if (criteria) { /* only if criteria defined */
|
yuuji@0
|
447 /* make writeable copy of criteria */
|
yuuji@0
|
448 criteria = cpystr (criteria);
|
yuuji@0
|
449 /* for each criterion */
|
yuuji@0
|
450 for (pgm = mail_newsearchpgm (), criterion = strtok_r (criteria," ",&r);
|
yuuji@0
|
451 criterion; (criterion = strtok_r (NIL," ",&r))) {
|
yuuji@0
|
452 f = NIL; /* init then scan the criterion */
|
yuuji@0
|
453 switch (*ucase (criterion)) {
|
yuuji@0
|
454 case 'A': /* possible ALL, ANSWERED */
|
yuuji@0
|
455 if (!strcmp (criterion+1,"LL")) f = T;
|
yuuji@0
|
456 else if (!strcmp (criterion+1,"NSWERED")) f = pgm->answered = T;
|
yuuji@0
|
457 break;
|
yuuji@0
|
458 case 'B': /* possible BCC, BEFORE, BODY */
|
yuuji@0
|
459 if (!strcmp (criterion+1,"CC"))
|
yuuji@0
|
460 f = mail_criteria_string (&pgm->bcc,&r);
|
yuuji@0
|
461 else if (!strcmp (criterion+1,"EFORE"))
|
yuuji@0
|
462 f = mail_criteria_date (&pgm->before,&r);
|
yuuji@0
|
463 else if (!strcmp (criterion+1,"ODY"))
|
yuuji@0
|
464 f = mail_criteria_string (&pgm->body,&r);
|
yuuji@0
|
465 break;
|
yuuji@0
|
466 case 'C': /* possible CC */
|
yuuji@0
|
467 if (!strcmp (criterion+1,"C")) f = mail_criteria_string (&pgm->cc,&r);
|
yuuji@0
|
468 break;
|
yuuji@0
|
469 case 'D': /* possible DELETED, DRAFT */
|
yuuji@0
|
470 if (!strcmp (criterion+1,"ELETED")) f = pgm->deleted = T;
|
yuuji@0
|
471 else if (!strcmp (criterion+1,"RAFT")) f = pgm->draft = T;
|
yuuji@0
|
472 break;
|
yuuji@0
|
473 case 'F': /* possible FLAGGED, FROM */
|
yuuji@0
|
474 if (!strcmp (criterion+1,"LAGGED")) f = pgm->flagged = T;
|
yuuji@0
|
475 else if (!strcmp (criterion+1,"ROM"))
|
yuuji@0
|
476 f = mail_criteria_string (&pgm->from,&r);
|
yuuji@0
|
477 break;
|
yuuji@0
|
478 case 'K': /* possible KEYWORD */
|
yuuji@0
|
479 if (!strcmp (criterion+1,"EYWORD"))
|
yuuji@0
|
480 f = mail_criteria_string (&pgm->keyword,&r);
|
yuuji@0
|
481 break;
|
yuuji@0
|
482 case 'L': /* possible LARGER */
|
yuuji@0
|
483 if (!strcmp (criterion+1,"ARGER"))
|
yuuji@0
|
484 f = prune_criteria_number (&pgm->larger,&r);
|
yuuji@0
|
485
|
yuuji@0
|
486 case 'N': /* possible NEW */
|
yuuji@0
|
487 if (!strcmp (criterion+1,"EW")) f = pgm->recent = pgm->unseen = T;
|
yuuji@0
|
488 break;
|
yuuji@0
|
489 case 'O': /* possible OLD, ON */
|
yuuji@0
|
490 if (!strcmp (criterion+1,"LD")) f = pgm->old = T;
|
yuuji@0
|
491 else if (!strcmp (criterion+1,"N"))
|
yuuji@0
|
492 f = mail_criteria_date (&pgm->on,&r);
|
yuuji@0
|
493 break;
|
yuuji@0
|
494 case 'R': /* possible RECENT */
|
yuuji@0
|
495 if (!strcmp (criterion+1,"ECENT")) f = pgm->recent = T;
|
yuuji@0
|
496 break;
|
yuuji@0
|
497 case 'S': /* possible SEEN, SENT*, SINCE, SMALLER,
|
yuuji@0
|
498 SUBJECT */
|
yuuji@0
|
499 if (!strcmp (criterion+1,"EEN")) f = pgm->seen = T;
|
yuuji@0
|
500 else if (!strncmp (criterion+1,"ENT",3)) {
|
yuuji@0
|
501 if (!strcmp (criterion+4,"BEFORE"))
|
yuuji@0
|
502 f = mail_criteria_date (&pgm->sentbefore,&r);
|
yuuji@0
|
503 else if (!strcmp (criterion+4,"ON"))
|
yuuji@0
|
504 f = mail_criteria_date (&pgm->senton,&r);
|
yuuji@0
|
505 else if (!strcmp (criterion+4,"SINCE"))
|
yuuji@0
|
506 f = mail_criteria_date (&pgm->sentsince,&r);
|
yuuji@0
|
507 }
|
yuuji@0
|
508 else if (!strcmp (criterion+1,"INCE"))
|
yuuji@0
|
509 f = mail_criteria_date (&pgm->since,&r);
|
yuuji@0
|
510 else if (!strcmp (criterion+1,"MALLER"))
|
yuuji@0
|
511 f = prune_criteria_number (&pgm->smaller,&r);
|
yuuji@0
|
512 else if (!strcmp (criterion+1,"UBJECT"))
|
yuuji@0
|
513 f = mail_criteria_string (&pgm->subject,&r);
|
yuuji@0
|
514 break;
|
yuuji@0
|
515 case 'T': /* possible TEXT, TO */
|
yuuji@0
|
516 if (!strcmp (criterion+1,"EXT"))
|
yuuji@0
|
517 f = mail_criteria_string (&pgm->text,&r);
|
yuuji@0
|
518 else if (!strcmp (criterion+1,"O"))
|
yuuji@0
|
519 f = mail_criteria_string (&pgm->to,&r);
|
yuuji@0
|
520 break;
|
yuuji@0
|
521 case 'U': /* possible UN* */
|
yuuji@0
|
522 if (criterion[1] == 'N') {
|
yuuji@0
|
523 if (!strcmp (criterion+2,"ANSWERED")) f = pgm->unanswered = T;
|
yuuji@0
|
524 else if (!strcmp (criterion+2,"DELETED")) f = pgm->undeleted = T;
|
yuuji@0
|
525 else if (!strcmp (criterion+2,"DRAFT")) f = pgm->undraft = T;
|
yuuji@0
|
526 else if (!strcmp (criterion+2,"FLAGGED")) f = pgm->unflagged = T;
|
yuuji@0
|
527 else if (!strcmp (criterion+2,"KEYWORD"))
|
yuuji@0
|
528 f = mail_criteria_string (&pgm->unkeyword,&r);
|
yuuji@0
|
529 else if (!strcmp (criterion+2,"SEEN")) f = pgm->unseen = T;
|
yuuji@0
|
530 }
|
yuuji@0
|
531 break;
|
yuuji@0
|
532 default: /* we will barf below */
|
yuuji@0
|
533 break;
|
yuuji@0
|
534 }
|
yuuji@0
|
535
|
yuuji@0
|
536 if (!f) { /* if can't identify criterion */
|
yuuji@0
|
537 sprintf (tmp,"Unknown search criterion: %.30s",criterion);
|
yuuji@0
|
538 MM_LOG (tmp,ERROR);
|
yuuji@0
|
539 mail_free_searchpgm (&pgm);
|
yuuji@0
|
540 break;
|
yuuji@0
|
541 }
|
yuuji@0
|
542 }
|
yuuji@0
|
543 /* no longer need copy of criteria */
|
yuuji@0
|
544 fs_give ((void **) &criteria);
|
yuuji@0
|
545 }
|
yuuji@0
|
546 return pgm;
|
yuuji@0
|
547 }
|
yuuji@0
|
548
|
yuuji@0
|
549
|
yuuji@0
|
550 /* Parse a number
|
yuuji@0
|
551 * Accepts: pointer to integer to return
|
yuuji@0
|
552 * pointer to strtok state
|
yuuji@0
|
553 * Returns: T if successful, else NIL
|
yuuji@0
|
554 */
|
yuuji@0
|
555
|
yuuji@0
|
556 int prune_criteria_number (unsigned long *number,char **r)
|
yuuji@0
|
557 {
|
yuuji@0
|
558 char *t;
|
yuuji@0
|
559 STRINGLIST *s = NIL;
|
yuuji@0
|
560 /* parse the date and return fn if OK */
|
yuuji@0
|
561 int ret = (mail_criteria_string (&s,r) &&
|
yuuji@0
|
562 (*number = strtoul ((char *) s->text.data,&t,10)) && !*t) ?
|
yuuji@0
|
563 T : NIL;
|
yuuji@0
|
564 if (s) mail_free_stringlist (&s);
|
yuuji@0
|
565 return ret;
|
yuuji@0
|
566 }
|
yuuji@0
|
567
|
yuuji@0
|
568 /* Copy mailbox
|
yuuji@0
|
569 * Accepts: stream open on source
|
yuuji@0
|
570 * halfopen stream for destination or NIL
|
yuuji@0
|
571 * destination mailbox name
|
yuuji@0
|
572 * non-zero to create destination mailbox
|
yuuji@0
|
573 * non-zero to delete messages from source after copying
|
yuuji@0
|
574 * merge mode
|
yuuji@0
|
575 * Returns: T if success, NIL if error
|
yuuji@0
|
576 */
|
yuuji@0
|
577
|
yuuji@0
|
578 int mbxcopy (MAILSTREAM *source,MAILSTREAM *dest,char *dst,int create,int del,
|
yuuji@0
|
579 int mode)
|
yuuji@0
|
580 {
|
yuuji@0
|
581 char *s,tmp[MAILTMPLEN];
|
yuuji@0
|
582 APPENDPACKAGE ap;
|
yuuji@0
|
583 STRING st;
|
yuuji@0
|
584 char *ndst = NIL;
|
yuuji@0
|
585 int ret = NIL;
|
yuuji@0
|
586 trycreate = NIL; /* no TRYCREATE yet */
|
yuuji@0
|
587 if (create) while (!mail_create (dest,dst) && (mode != mAPPEND)) {
|
yuuji@0
|
588 switch (mode) {
|
yuuji@0
|
589 case mPROMPT: /* prompt user for new name */
|
yuuji@0
|
590 tmp[0] = '\0';
|
yuuji@0
|
591 while (!tmp[0]) { /* read name */
|
yuuji@0
|
592 fputs ("alternative name: ",stdout);
|
yuuji@0
|
593 fflush (stdout);
|
yuuji@0
|
594 fgets (tmp,MAILTMPLEN-1,stdin);
|
yuuji@0
|
595 if (s = strchr (tmp,'\n')) *s = '\0';
|
yuuji@0
|
596 }
|
yuuji@0
|
597 if (ndst) fs_give ((void **) &ndst);
|
yuuji@0
|
598 ndst = cpystr (tmp);
|
yuuji@0
|
599 break;
|
yuuji@0
|
600 case mSUFFIX: /* try again with new suffix */
|
yuuji@0
|
601 if (ndst) fs_give ((void **) &ndst);
|
yuuji@0
|
602 sprintf (ndst = (char *) fs_get (strlen (dst) + strlen (suffix) + 1),
|
yuuji@0
|
603 "%s%s",dst,suffix);
|
yuuji@0
|
604 printf ("retry to create %s\n",ndst);
|
yuuji@0
|
605 mode = mPROMPT; /* switch to prompt mode if name fails */
|
yuuji@0
|
606 break;
|
yuuji@0
|
607 case NIL: /* not merging */
|
yuuji@0
|
608 return NIL;
|
yuuji@0
|
609 }
|
yuuji@0
|
610 if (ndst) dst = ndst; /* if alternative name given, use it */
|
yuuji@0
|
611 }
|
yuuji@0
|
612
|
yuuji@0
|
613 if (kwcopyp) {
|
yuuji@0
|
614 int i;
|
yuuji@0
|
615 size_t len;
|
yuuji@0
|
616 char *dummymsg = "Date: Thu, 18 May 2006 00:00 -0700\r\nFrom: dummy@example.com\r\nSubject: dummy\r\n\r\ndummy\r\n";
|
yuuji@0
|
617 for (i = 0,len = 0; i < NUSERFLAGS; ++i)
|
yuuji@0
|
618 if (source->user_flags[i]) len += strlen (source->user_flags[i]) + 1;
|
yuuji@0
|
619 if (len) { /* easy if no user flags to copy... */
|
yuuji@0
|
620 char *t;
|
yuuji@0
|
621 char *tail = "\\Deleted)";
|
yuuji@0
|
622 char *flags = (char *) fs_get (1 + len + strlen (tail) + 1);
|
yuuji@0
|
623 s = flags; *s++ = '(';
|
yuuji@0
|
624 for (i = 0; i < NUSERFLAGS; ++i) if (t = source->user_flags[i]) {
|
yuuji@0
|
625 while (*t) *s++ = *t++;
|
yuuji@0
|
626 *s++ = ' ';
|
yuuji@0
|
627 }
|
yuuji@0
|
628 strcpy (s,tail); /* terminate flags list */
|
yuuji@0
|
629 if ((dst[0] == '#') && ((dst[1] == 'D') || (dst[1] == 'd')) &&
|
yuuji@0
|
630 ((dst[2] == 'R') || (dst[2] == 'r')) &&
|
yuuji@0
|
631 ((dst[3] == 'I') || (dst[3] == 'i')) &&
|
yuuji@0
|
632 ((dst[4] == 'V') || (dst[4] == 'v')) &&
|
yuuji@0
|
633 ((dst[5] == 'E') || (dst[5] == 'e')) &&
|
yuuji@0
|
634 ((dst[6] == 'R') || (dst[6] == 'r')) && (dst[7] == '.') &&
|
yuuji@0
|
635 (t = strchr (dst+8,'/'))) ++t;
|
yuuji@0
|
636 else t = dst;
|
yuuji@0
|
637 INIT (&st,mail_string,dummymsg,strlen (dummymsg));
|
yuuji@0
|
638 if (!(mail_append (dest,dst,&st) &&
|
yuuji@0
|
639 (dest = mail_open (dest,t,debugp ? OP_DEBUG : NIL)))) {
|
yuuji@0
|
640 fs_give ((void **) &flags);
|
yuuji@0
|
641 return NIL;
|
yuuji@0
|
642 }
|
yuuji@0
|
643 mail_setflag (dest,"*",flags);
|
yuuji@0
|
644 mail_expunge (dest);
|
yuuji@0
|
645 fs_give ((void **) &flags);
|
yuuji@0
|
646 }
|
yuuji@0
|
647 }
|
yuuji@0
|
648
|
yuuji@0
|
649 if (source->nmsgs) { /* non-empty source */
|
yuuji@0
|
650 if (verbosep) printf ("%s [%lu message(s)] => %s\n",
|
yuuji@0
|
651 source->mailbox,source->nmsgs,dst);
|
yuuji@0
|
652 ap.stream = source; /* prepare append package */
|
yuuji@0
|
653 ap.msgno = 0;
|
yuuji@0
|
654 ap.msgmax = source->nmsgs;
|
yuuji@0
|
655 ap.flags = ap.date = NIL;
|
yuuji@0
|
656 ap.message = &st;
|
yuuji@0
|
657 /* make sure we have all messages */
|
yuuji@0
|
658 sprintf (tmp,"1:%lu",ap.msgmax);
|
yuuji@0
|
659 mail_fetchfast (source,tmp);
|
yuuji@0
|
660 if (mail_append_multiple (dest,dst,mm_append,(void *) &ap)) {
|
yuuji@0
|
661 --ap.msgno; /* make sure user knows it won */
|
yuuji@0
|
662 if (verbosep) printf ("[Ok %lu messages(s)]\n",ap.msgno);
|
yuuji@0
|
663 if (del && ap.msgno) { /* delete source messages */
|
yuuji@0
|
664 sprintf (tmp,"1:%lu",ap.msgno);
|
yuuji@0
|
665 mail_flag (source,tmp,"\\Deleted",ST_SET);
|
yuuji@0
|
666 /* flush moved messages */
|
yuuji@0
|
667 mail_expunge (source);
|
yuuji@0
|
668 }
|
yuuji@0
|
669 ret = T;
|
yuuji@0
|
670 }
|
yuuji@0
|
671 else if ((mode == mAPPEND) && trycreate)
|
yuuji@0
|
672 ret = mbxcopy (source,dest,dst,create,del,mPROMPT);
|
yuuji@0
|
673 else if (verbosep) puts ("[Failed]");
|
yuuji@0
|
674 }
|
yuuji@0
|
675 else { /* empty source */
|
yuuji@0
|
676 if (verbosep) printf ("%s [empty] => %s\n",source->mailbox,dst);
|
yuuji@0
|
677 ret = T;
|
yuuji@0
|
678 }
|
yuuji@0
|
679 if (ndst) fs_give ((void **) &ndst);
|
yuuji@0
|
680 return ret;
|
yuuji@0
|
681 }
|
yuuji@0
|
682
|
yuuji@0
|
683 /* Append callback
|
yuuji@0
|
684 * Accepts: mail stream
|
yuuji@0
|
685 * append package
|
yuuji@0
|
686 * pointer to return flags
|
yuuji@0
|
687 * pointer to return date
|
yuuji@0
|
688 * pointer to return message stringstruct
|
yuuji@0
|
689 * Returns: T on success
|
yuuji@0
|
690 */
|
yuuji@0
|
691
|
yuuji@0
|
692 long mm_append (MAILSTREAM *stream,void *data,char **flags,char **date,
|
yuuji@0
|
693 STRING **message)
|
yuuji@0
|
694 {
|
yuuji@0
|
695 char *t,*t1,tmp[MAILTMPLEN];
|
yuuji@0
|
696 unsigned long u;
|
yuuji@0
|
697 MESSAGECACHE *elt;
|
yuuji@0
|
698 APPENDPACKAGE *ap = (APPENDPACKAGE *) data;
|
yuuji@0
|
699 *flags = *date = NIL; /* assume no flags or date */
|
yuuji@0
|
700 if (ap->flags) fs_give ((void **) &ap->flags);
|
yuuji@0
|
701 if (ap->date) fs_give ((void **) &ap->date);
|
yuuji@0
|
702 mail_gc (ap->stream,GC_TEXTS);
|
yuuji@0
|
703 if (++ap->msgno <= ap->msgmax) {
|
yuuji@0
|
704 /* initialize flag string */
|
yuuji@0
|
705 memset (t = tmp,0,MAILTMPLEN);
|
yuuji@0
|
706 /* output system flags */
|
yuuji@0
|
707 if ((elt = mail_elt (ap->stream,ap->msgno))->seen) strcat (t," \\Seen");
|
yuuji@0
|
708 if (elt->deleted) strcat (t," \\Deleted");
|
yuuji@0
|
709 if (elt->flagged) strcat (t," \\Flagged");
|
yuuji@0
|
710 if (elt->answered) strcat (t," \\Answered");
|
yuuji@0
|
711 if (elt->draft) strcat (t," \\Draft");
|
yuuji@0
|
712 /* any user flags? */
|
yuuji@0
|
713 if (!ignorep && (u = elt->user_flags)) do
|
yuuji@0
|
714 if ((t1 = ap->stream->user_flags[find_rightmost_bit (&u)]) &&
|
yuuji@0
|
715 (MAILTMPLEN - ((t += strlen (t)) - tmp)) > (long) (2 + strlen (t1))){
|
yuuji@0
|
716 *t++ = ' '; /* space delimiter */
|
yuuji@0
|
717 strcpy (t,t1); /* copy the user flag */
|
yuuji@0
|
718 }
|
yuuji@0
|
719 while (u); /* until no more user flags */
|
yuuji@0
|
720 *flags = ap->flags = cpystr (tmp + 1);
|
yuuji@0
|
721 *date = ap->date = cpystr (mail_date (tmp,elt));
|
yuuji@0
|
722 *message = ap->message; /* message stringstruct */
|
yuuji@0
|
723 INIT (ap->message,mstring,(void *) ap,elt->rfc822_size);
|
yuuji@0
|
724 }
|
yuuji@0
|
725 else *message = NIL; /* all done */
|
yuuji@0
|
726 return LONGT;
|
yuuji@0
|
727 }
|
yuuji@0
|
728
|
yuuji@0
|
729 /* Co-routines from MAIL library */
|
yuuji@0
|
730
|
yuuji@0
|
731
|
yuuji@0
|
732 /* Message matches a search
|
yuuji@0
|
733 * Accepts: MAIL stream
|
yuuji@0
|
734 * message number
|
yuuji@0
|
735 */
|
yuuji@0
|
736
|
yuuji@0
|
737 void mm_searched (MAILSTREAM *stream,unsigned long msgno)
|
yuuji@0
|
738 {
|
yuuji@0
|
739 /* dummy routine */
|
yuuji@0
|
740 }
|
yuuji@0
|
741
|
yuuji@0
|
742
|
yuuji@0
|
743 /* Message exists (i.e. there are that many messages in the mailbox)
|
yuuji@0
|
744 * Accepts: MAIL stream
|
yuuji@0
|
745 * message number
|
yuuji@0
|
746 */
|
yuuji@0
|
747
|
yuuji@0
|
748 void mm_exists (MAILSTREAM *stream,unsigned long number)
|
yuuji@0
|
749 {
|
yuuji@0
|
750 /* dummy routine */
|
yuuji@0
|
751 }
|
yuuji@0
|
752
|
yuuji@0
|
753
|
yuuji@0
|
754 /* Message expunged
|
yuuji@0
|
755 * Accepts: MAIL stream
|
yuuji@0
|
756 * message number
|
yuuji@0
|
757 */
|
yuuji@0
|
758
|
yuuji@0
|
759 void mm_expunged (MAILSTREAM *stream,unsigned long number)
|
yuuji@0
|
760 {
|
yuuji@0
|
761 /* dummy routine */
|
yuuji@0
|
762 }
|
yuuji@0
|
763
|
yuuji@0
|
764
|
yuuji@0
|
765 /* Message flags update seen
|
yuuji@0
|
766 * Accepts: MAIL stream
|
yuuji@0
|
767 * message number
|
yuuji@0
|
768 */
|
yuuji@0
|
769
|
yuuji@0
|
770 void mm_flags (MAILSTREAM *stream,unsigned long number)
|
yuuji@0
|
771 {
|
yuuji@0
|
772 /* dummy routine */
|
yuuji@0
|
773 }
|
yuuji@0
|
774
|
yuuji@0
|
775 /* Mailbox found
|
yuuji@0
|
776 * Accepts: MAIL stream
|
yuuji@0
|
777 * hierarchy delimiter
|
yuuji@0
|
778 * mailbox name
|
yuuji@0
|
779 * mailbox attributes
|
yuuji@0
|
780 */
|
yuuji@0
|
781
|
yuuji@0
|
782 void mm_list (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
yuuji@0
|
783 {
|
yuuji@0
|
784 /* note destination delimiter */
|
yuuji@0
|
785 if (ddelim < 0) ddelim = delimiter;
|
yuuji@0
|
786 /* if got a selectable name */
|
yuuji@0
|
787 else if (!(attributes & LATT_NOSELECT) && *name)
|
yuuji@0
|
788 fprintf (f,"%c%s\n",delimiter,name);
|
yuuji@0
|
789 }
|
yuuji@0
|
790
|
yuuji@0
|
791
|
yuuji@0
|
792 /* Subscribe mailbox found
|
yuuji@0
|
793 * Accepts: MAIL stream
|
yuuji@0
|
794 * hierarchy delimiter
|
yuuji@0
|
795 * mailbox name
|
yuuji@0
|
796 * mailbox attributes
|
yuuji@0
|
797 */
|
yuuji@0
|
798
|
yuuji@0
|
799 void mm_lsub (MAILSTREAM *stream,int delimiter,char *name,long attributes)
|
yuuji@0
|
800 {
|
yuuji@0
|
801 /* dummy routine */
|
yuuji@0
|
802 }
|
yuuji@0
|
803
|
yuuji@0
|
804
|
yuuji@0
|
805 /* Mailbox status
|
yuuji@0
|
806 * Accepts: MAIL stream
|
yuuji@0
|
807 * mailbox name
|
yuuji@0
|
808 * mailbox status
|
yuuji@0
|
809 */
|
yuuji@0
|
810
|
yuuji@0
|
811 void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
|
yuuji@0
|
812 {
|
yuuji@0
|
813 if (status->recent || status->unseen)
|
yuuji@0
|
814 printf ("%lu new message(s) (%lu unseen),",status->recent,status->unseen);
|
yuuji@0
|
815 else fputs ("No new messages,",stdout);
|
yuuji@0
|
816 printf (" %lu total in %s\n",status->messages,mailbox);
|
yuuji@0
|
817 }
|
yuuji@0
|
818
|
yuuji@0
|
819 /* Notification event
|
yuuji@0
|
820 * Accepts: MAIL stream
|
yuuji@0
|
821 * string to log
|
yuuji@0
|
822 * error flag
|
yuuji@0
|
823 */
|
yuuji@0
|
824
|
yuuji@0
|
825 void mm_notify (MAILSTREAM *stream,char *string,long errflg)
|
yuuji@0
|
826 {
|
yuuji@0
|
827 if (!errflg && (string[0] == '[') &&
|
yuuji@0
|
828 ((string[1] == 'T') || (string[1] == 't')) &&
|
yuuji@0
|
829 ((string[2] == 'R') || (string[2] == 'r')) &&
|
yuuji@0
|
830 ((string[3] == 'Y') || (string[3] == 'y')) &&
|
yuuji@0
|
831 ((string[4] == 'C') || (string[4] == 'c')) &&
|
yuuji@0
|
832 ((string[5] == 'R') || (string[5] == 'r')) &&
|
yuuji@0
|
833 ((string[6] == 'E') || (string[6] == 'e')) &&
|
yuuji@0
|
834 ((string[7] == 'A') || (string[7] == 'a')) &&
|
yuuji@0
|
835 ((string[8] == 'T') || (string[8] == 't')) &&
|
yuuji@0
|
836 ((string[9] == 'E') || (string[9] == 'e')) &&
|
yuuji@0
|
837 (string[10] == ']'))
|
yuuji@0
|
838 trycreate = T;
|
yuuji@0
|
839 mm_log (string,errflg); /* just do mm_log action */
|
yuuji@0
|
840 }
|
yuuji@0
|
841
|
yuuji@0
|
842
|
yuuji@0
|
843 /* Log an event for the user to see
|
yuuji@0
|
844 * Accepts: string to log
|
yuuji@0
|
845 * error flag
|
yuuji@0
|
846 */
|
yuuji@0
|
847
|
yuuji@0
|
848 void mm_log (char *string,long errflg)
|
yuuji@0
|
849 {
|
yuuji@0
|
850 switch (errflg) {
|
yuuji@0
|
851 case BYE:
|
yuuji@0
|
852 case NIL: /* no error */
|
yuuji@0
|
853 if (verbosep) fprintf (stderr,"[%s]\n",string);
|
yuuji@0
|
854 break;
|
yuuji@0
|
855 case PARSE: /* parsing problem */
|
yuuji@0
|
856 case WARN: /* warning */
|
yuuji@0
|
857 fprintf (stderr,"warning: %s\n",string);
|
yuuji@0
|
858 break;
|
yuuji@0
|
859 case ERROR: /* error */
|
yuuji@0
|
860 default:
|
yuuji@0
|
861 fprintf (stderr,"%s\n",string);
|
yuuji@0
|
862 break;
|
yuuji@0
|
863 }
|
yuuji@0
|
864 }
|
yuuji@0
|
865
|
yuuji@0
|
866
|
yuuji@0
|
867 /* Log an event to debugging telemetry
|
yuuji@0
|
868 * Accepts: string to log
|
yuuji@0
|
869 */
|
yuuji@0
|
870
|
yuuji@0
|
871 void mm_dlog (char *string)
|
yuuji@0
|
872 {
|
yuuji@0
|
873 fprintf (stderr,"%s\n",string);
|
yuuji@0
|
874 }
|
yuuji@0
|
875
|
yuuji@0
|
876 /* Get user name and password for this host
|
yuuji@0
|
877 * Accepts: parse of network mailbox name
|
yuuji@0
|
878 * where to return user name
|
yuuji@0
|
879 * where to return password
|
yuuji@0
|
880 * trial count
|
yuuji@0
|
881 */
|
yuuji@0
|
882
|
yuuji@0
|
883 void mm_login (NETMBX *mb,char *username,char *password,long trial)
|
yuuji@0
|
884 {
|
yuuji@0
|
885 char *s,tmp[MAILTMPLEN];
|
yuuji@0
|
886 sprintf (s = tmp,"{%s/%s",mb->host,mb->service);
|
yuuji@0
|
887 if (*mb->user) sprintf (tmp+strlen (tmp),"/user=%s",
|
yuuji@0
|
888 strcpy (username,mb->user));
|
yuuji@0
|
889 if (*mb->authuser) sprintf (tmp+strlen (tmp),"/authuser=%s",mb->authuser);
|
yuuji@0
|
890 if (*mb->user) strcat (s = tmp,"} password:");
|
yuuji@0
|
891 else {
|
yuuji@0
|
892 printf ("%s} username: ",tmp);
|
yuuji@0
|
893 fgets (username,NETMAXUSER-1,stdin);
|
yuuji@0
|
894 username[NETMAXUSER-1] = '\0';
|
yuuji@0
|
895 if (s = strchr (username,'\n')) *s = '\0';
|
yuuji@0
|
896 s = "password: ";
|
yuuji@0
|
897 }
|
yuuji@0
|
898 strcpy (password,getpass (s));
|
yuuji@0
|
899 }
|
yuuji@0
|
900
|
yuuji@0
|
901
|
yuuji@0
|
902 /* About to enter critical code
|
yuuji@0
|
903 * Accepts: stream
|
yuuji@0
|
904 */
|
yuuji@0
|
905
|
yuuji@0
|
906 void mm_critical (MAILSTREAM *stream)
|
yuuji@0
|
907 {
|
yuuji@0
|
908 critical = T; /* note in critical code */
|
yuuji@0
|
909 }
|
yuuji@0
|
910
|
yuuji@0
|
911
|
yuuji@0
|
912 /* About to exit critical code
|
yuuji@0
|
913 * Accepts: stream
|
yuuji@0
|
914 */
|
yuuji@0
|
915
|
yuuji@0
|
916 void mm_nocritical (MAILSTREAM *stream)
|
yuuji@0
|
917 {
|
yuuji@0
|
918 critical = NIL; /* note not in critical code */
|
yuuji@0
|
919 }
|
yuuji@0
|
920
|
yuuji@0
|
921
|
yuuji@0
|
922 /* Disk error found
|
yuuji@0
|
923 * Accepts: stream
|
yuuji@0
|
924 * system error code
|
yuuji@0
|
925 * flag indicating that mailbox may be clobbered
|
yuuji@0
|
926 * Returns: T if user wants to abort
|
yuuji@0
|
927 */
|
yuuji@0
|
928
|
yuuji@0
|
929 long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
|
yuuji@0
|
930 {
|
yuuji@0
|
931 return T;
|
yuuji@0
|
932 }
|
yuuji@0
|
933
|
yuuji@0
|
934
|
yuuji@0
|
935 /* Log a fatal error event
|
yuuji@0
|
936 * Accepts: string to log
|
yuuji@0
|
937 */
|
yuuji@0
|
938
|
yuuji@0
|
939 void mm_fatal (char *string)
|
yuuji@0
|
940 {
|
yuuji@0
|
941 fprintf (stderr,"FATAL: %s\n",string);
|
yuuji@0
|
942 }
|