136 |
}; |
}; |
137 |
|
|
138 |
static char * |
static char * |
139 |
msgset_preproc (mailbox_t mbox, char *arg) |
msgset_preproc_part (mailbox_t mbox, char *arg, char **rest) |
140 |
{ |
{ |
141 |
struct msgset_keyword *p; |
struct msgset_keyword *p; |
142 |
|
|
143 |
for (p = keywords; p->name; p++) |
for (p = keywords; p->name; p++) |
144 |
if (strncmp (arg, p->name, strlen (p->name)) == 0) |
if (strncmp (arg, p->name, strlen (p->name)) == 0) |
145 |
{ |
{ |
157 |
exit (1); |
exit (1); |
158 |
} |
} |
159 |
message_get_uid (msg, &uid); |
message_get_uid (msg, &uid); |
160 |
asprintf (&ret, "%lu%s", (unsigned long) uid, arg + strlen (p->name)); |
asprintf (&ret, "%lu", (unsigned long) uid); |
161 |
|
*rest = arg + strlen (p->name); |
162 |
return ret; |
return ret; |
163 |
} |
} |
164 |
|
*rest = arg + strlen (arg); |
165 |
return strdup (arg); |
return strdup (arg); |
166 |
} |
} |
167 |
|
|
168 |
|
static char * |
169 |
|
msgset_preproc (mailbox_t mbox, char *arg) |
170 |
|
{ |
171 |
|
char *buf, *tail; |
172 |
|
|
173 |
|
if (strcmp (arg, "all") == 0) |
174 |
|
{ |
175 |
|
/* Special case */ |
176 |
|
arg = "first-last"; |
177 |
|
} |
178 |
|
|
179 |
|
buf = msgset_preproc_part (mbox, arg, &tail); |
180 |
|
if (tail[0] == '-') |
181 |
|
{ |
182 |
|
char *rest = msgset_preproc_part (mbox, tail+1, &tail); |
183 |
|
char *p = NULL; |
184 |
|
asprintf (&p, "%s-%s", buf, rest); |
185 |
|
free (rest); |
186 |
|
free (buf); |
187 |
|
buf = p; |
188 |
|
} |
189 |
|
|
190 |
|
if (tail[0]) |
191 |
|
{ |
192 |
|
char *p = NULL; |
193 |
|
asprintf (&p, "%s%s", buf, tail); |
194 |
|
free (buf); |
195 |
|
buf = p; |
196 |
|
} |
197 |
|
return buf; |
198 |
|
} |
199 |
|
|
200 |
static int |
static int |
201 |
comp_mesg (const void *a, const void *b) |
comp_mesg (const void *a, const void *b) |
202 |
{ |
{ |
229 |
{ |
{ |
230 |
char *p = NULL; |
char *p = NULL; |
231 |
size_t start, end; |
size_t start, end; |
232 |
|
size_t msg_first, n; |
233 |
long num; |
long num; |
234 |
char *arg = msgset_preproc (mbox, argv[i]); |
char *arg = msgset_preproc (mbox, argv[i]); |
235 |
start = strtoul (arg, &p, 0); |
start = strtoul (arg, &p, 0); |
236 |
switch (*p) |
switch (*p) |
237 |
{ |
{ |
238 |
case 0: |
case 0: |
239 |
msglist[msgno++] = start; |
n = mh_get_message (mbox, start, NULL); |
240 |
|
if (!n) |
241 |
|
{ |
242 |
|
mh_error ("message %d does not exist", start); |
243 |
|
exit (1); |
244 |
|
} |
245 |
|
msglist[msgno++] = n; |
246 |
break; |
break; |
247 |
|
|
248 |
case '-': |
case '-': |
256 |
end = t; |
end = t; |
257 |
} |
} |
258 |
_expand (&msgcnt, &msglist, end - start); |
_expand (&msgcnt, &msglist, end - start); |
259 |
|
msg_first = msgno; |
260 |
for (; start <= end; start++) |
for (; start <= end; start++) |
261 |
msglist[msgno++] = start; |
{ |
262 |
|
n = mh_get_message (mbox, start, NULL); |
263 |
|
if (n) |
264 |
|
msglist[msgno++] = n; |
265 |
|
} |
266 |
|
if (msgno == msg_first) |
267 |
|
{ |
268 |
|
mh_error ("no messages in range %s", argv[i]); |
269 |
|
exit (1); |
270 |
|
} |
271 |
break; |
break; |
272 |
|
|
273 |
case ':': |
case ':': |
278 |
if (end < start) |
if (end < start) |
279 |
{ |
{ |
280 |
size_t t = start; |
size_t t = start; |
281 |
start = end; |
start = end + 1; |
282 |
end = t; |
end = t; |
283 |
} |
} |
284 |
|
else |
285 |
|
end--; |
286 |
_expand (&msgcnt, &msglist, end - start); |
_expand (&msgcnt, &msglist, end - start); |
287 |
|
msg_first = msgno; |
288 |
for (; start <= end; start++) |
for (; start <= end; start++) |
289 |
msglist[msgno++] = start; |
{ |
290 |
|
n = mh_get_message (mbox, start, NULL); |
291 |
|
if (n) |
292 |
|
msglist[msgno++] = n; |
293 |
|
} |
294 |
|
if (msgno == msg_first) |
295 |
|
{ |
296 |
|
mh_error ("no messages in range %s", argv[i]); |
297 |
|
exit (1); |
298 |
|
} |
299 |
break; |
break; |
300 |
|
|
301 |
default: |
default: |
304 |
free (arg); |
free (arg); |
305 |
} |
} |
306 |
|
|
307 |
|
msgcnt = msgno; |
308 |
|
|
309 |
/* Sort the resulting message set */ |
/* Sort the resulting message set */ |
310 |
qsort (msglist, msgcnt, sizeof (*msglist), comp_mesg); |
qsort (msglist, msgcnt, sizeof (*msglist), comp_mesg); |
311 |
|
|
330 |
return i + 1; |
return i + 1; |
331 |
return 0; |
return 0; |
332 |
} |
} |
333 |
|
|
334 |
|
/* Auxiliary function. Performs binary search for a message with the |
335 |
|
given sequence number */ |
336 |
|
static size_t |
337 |
|
mh_search_message (mailbox_t mbox, size_t start, size_t stop, |
338 |
|
size_t seqno, message_t *mesg) |
339 |
|
{ |
340 |
|
message_t mid_msg = NULL; |
341 |
|
size_t num = 0, middle; |
342 |
|
|
343 |
|
middle = (start + stop) / 2; |
344 |
|
if (mailbox_get_message (mbox, middle, &mid_msg) |
345 |
|
|| mh_message_number (mid_msg, &num)) |
346 |
|
return 0; |
347 |
|
|
348 |
|
if (num == seqno) |
349 |
|
{ |
350 |
|
if (mesg) |
351 |
|
*mesg = mid_msg; |
352 |
|
return middle; |
353 |
|
} |
354 |
|
|
355 |
|
if (start >= stop) |
356 |
|
return 0; |
357 |
|
|
358 |
|
if (num > seqno) |
359 |
|
return mh_search_message (mbox, start, middle-1, seqno, mesg); |
360 |
|
else /*if (num < seqno)*/ |
361 |
|
return mh_search_message (mbox, middle+1, stop, seqno, mesg); |
362 |
|
} |
363 |
|
|
364 |
|
/* Retrieve the message with the given sequence number. |
365 |
|
Returns ordinal number of the message in the mailbox if found, |
366 |
|
zero otherwise. The retrieved message is stored in the location |
367 |
|
pointed to by mesg, unless it is NULL. */ |
368 |
|
|
369 |
|
size_t |
370 |
|
mh_get_message (mailbox_t mbox, size_t seqno, message_t *mesg) |
371 |
|
{ |
372 |
|
size_t num, count; |
373 |
|
message_t msg; |
374 |
|
|
375 |
|
if (mailbox_get_message (mbox, 1, &msg) |
376 |
|
|| mh_message_number (msg, &num)) |
377 |
|
return 0; |
378 |
|
if (seqno < num) |
379 |
|
return 0; |
380 |
|
else if (seqno == num) |
381 |
|
{ |
382 |
|
if (mesg) |
383 |
|
*mesg = msg; |
384 |
|
return 1; |
385 |
|
} |
386 |
|
|
387 |
|
if (mailbox_messages_count (mbox, &count) |
388 |
|
|| mailbox_get_message (mbox, count, &msg) |
389 |
|
|| mh_message_number (msg, &num)) |
390 |
|
return 0; |
391 |
|
if (seqno > num) |
392 |
|
return 0; |
393 |
|
else if (seqno == num) |
394 |
|
{ |
395 |
|
if (mesg) |
396 |
|
*mesg = msg; |
397 |
|
return count; |
398 |
|
} |
399 |
|
|
400 |
|
return mh_search_message (mbox, 1, count, seqno, mesg); |
401 |
|
} |
402 |
|
|