25 |
|
|
26 |
char *current_folder = NULL; |
char *current_folder = NULL; |
27 |
size_t current_message = 0; |
size_t current_message = 0; |
28 |
char *ctx_name; |
mh_context_t *context; |
29 |
header_t ctx_header; |
mh_context_t *profile; |
30 |
header_t profile_header; |
mh_context_t *sequences; |
31 |
|
|
32 |
char mh_list_format[] = |
char mh_list_format[] = |
33 |
"%4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>" |
"%4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>" |
62 |
mh_init2 () |
mh_init2 () |
63 |
{ |
{ |
64 |
char *mh_sequences_name; |
char *mh_sequences_name; |
65 |
|
char *seq_name, *ctx_name; |
66 |
|
char *p; |
67 |
|
|
68 |
/* Set MH context */ |
mu_path_folder_dir = mh_get_dir (); |
69 |
|
p = getenv ("CONTEXT"); |
70 |
|
if (!p) |
71 |
|
p = "context"; |
72 |
|
ctx_name = mh_expand_name (p, 0); |
73 |
|
context = mh_context_create (ctx_name, 1); |
74 |
|
mh_context_read (context); |
75 |
|
|
76 |
if (current_folder) |
if (current_folder) |
77 |
current_folder = mu_tilde_expansion (current_folder, "/", NULL); |
current_folder = mu_tilde_expansion (current_folder, "/", NULL); |
78 |
else |
else |
79 |
current_folder = mh_profile_value ("Current-Folder", |
current_folder = mh_context_get_value (context, "Current-Folder", |
80 |
mh_profile_value ("Inbox", "inbox")); |
mh_profile_value ("Inbox", |
81 |
if (strchr (current_folder, '/') == NULL) |
"inbox")); |
|
{ |
|
|
char *mhdir = mh_profile_value ("Path", "Mail"); |
|
|
char *p = mu_get_homedir (); |
|
|
|
|
|
if (mhdir[0] == '/') |
|
|
asprintf (¤t_folder, "mh:%s/%s", mhdir, current_folder); |
|
|
else |
|
|
asprintf (¤t_folder, "mh:%s/%s/%s", p, mhdir, current_folder); |
|
|
if (!current_folder) |
|
|
{ |
|
|
mh_error ("low memory"); |
|
|
exit (1); |
|
|
} |
|
|
free (p); |
|
|
} |
|
|
else if (strchr (current_folder, ':') == NULL) |
|
|
{ |
|
|
char *p; |
|
|
p = xmalloc (strlen (current_folder) + 4); |
|
|
strcat (strcpy (p, "mh:"), current_folder); |
|
|
current_folder = p; |
|
|
} |
|
82 |
|
|
83 |
mh_sequences_name = mh_profile_value ("mh-sequences", MH_SEQUENCES_FILE); |
mh_sequences_name = mh_profile_value ("mh-sequences", MH_SEQUENCES_FILE); |
84 |
asprintf (&ctx_name, "%s/%s", current_folder+3, mh_sequences_name); |
asprintf (&seq_name, "%s/%s", current_folder+3, mh_sequences_name); |
85 |
if (mh_read_context_file (ctx_name, &ctx_header) == 0) |
sequences = mh_context_create (seq_name, 1); |
86 |
|
if (mh_context_read (sequences) == 0) |
87 |
{ |
{ |
88 |
char buf[64]; |
char *p = mh_context_get_value (sequences, "cur", "0"); |
89 |
size_t n; |
current_message = strtoul (p, NULL, 10); |
|
|
|
|
if (!header_get_value (ctx_header, "cur", buf, sizeof buf, &n)) |
|
|
current_message = strtoul (buf, NULL, 10); |
|
90 |
} |
} |
91 |
} |
} |
92 |
|
|
93 |
char * |
char * |
94 |
mh_profile_value (char *name, char *defval) |
mh_profile_value (char *name, char *defval) |
95 |
{ |
{ |
96 |
char *p; |
return mh_context_get_value (profile, name, defval); |
|
if (header_aget_value (profile_header, name, &p)) |
|
|
p = defval; |
|
|
return p; |
|
97 |
} |
} |
98 |
|
|
99 |
void |
void |
112 |
asprintf (&p, "%s/%s", home, MH_USER_PROFILE); |
asprintf (&p, "%s/%s", home, MH_USER_PROFILE); |
113 |
free (home); |
free (home); |
114 |
} |
} |
115 |
mh_read_context_file (p, &profile_header); |
profile = mh_context_create (p, 1); |
116 |
|
mh_context_read (profile); |
117 |
} |
} |
118 |
|
|
119 |
void |
void |
121 |
{ |
{ |
122 |
char buf[64]; |
char buf[64]; |
123 |
snprintf (buf, sizeof buf, "%d", current_message); |
snprintf (buf, sizeof buf, "%d", current_message); |
124 |
if (!ctx_header) |
mh_context_set_value (sequences, "cur", buf); |
125 |
{ |
mh_context_write (sequences); |
|
if (header_create (&ctx_header, NULL, 0, NULL)) |
|
|
{ |
|
|
mh_error ("Can't create context: %s", strerror (errno)); |
|
|
return; |
|
|
} |
|
|
} |
|
|
header_set_value (ctx_header, "cur", buf, 1); |
|
|
mh_write_context_file (ctx_name, ctx_header); |
|
|
} |
|
|
|
|
|
int |
|
|
mh_read_context_file (char *path, header_t *header) |
|
|
{ |
|
|
int status; |
|
|
char *blurb; |
|
|
struct stat st; |
|
|
FILE *fp; |
|
|
|
|
|
if (stat (path, &st)) |
|
|
return errno; |
|
|
|
|
|
blurb = malloc (st.st_size); |
|
|
if (!blurb) |
|
|
return ENOMEM; |
|
|
|
|
|
fp = fopen (path, "r"); |
|
|
if (!fp) |
|
|
{ |
|
|
free (blurb); |
|
|
return errno; |
|
|
} |
|
|
|
|
|
fread (blurb, st.st_size, 1, fp); |
|
|
fclose (fp); |
|
|
|
|
|
if (status = header_create (header, blurb, st.st_size, NULL)) |
|
|
free (blurb); |
|
|
|
|
|
return status; |
|
|
} |
|
|
|
|
|
int |
|
|
mh_write_context_file (char *path, header_t header) |
|
|
{ |
|
|
stream_t stream; |
|
|
char buffer[512]; |
|
|
size_t off = 0, n; |
|
|
FILE *fp; |
|
|
|
|
|
fp = fopen (path, "w"); |
|
|
if (!fp) |
|
|
{ |
|
|
mh_error ("can't write context file %s: %s", path, strerror (errno)); |
|
|
return 1; |
|
|
} |
|
|
|
|
|
header_get_stream (header, &stream); |
|
|
|
|
|
while (stream_read (stream, buffer, sizeof buffer - 1, off, &n) == 0 |
|
|
&& n != 0) |
|
|
{ |
|
|
buffer[n] = '\0'; |
|
|
fprintf (fp, "%s", buffer); |
|
|
off += n; |
|
|
} |
|
|
|
|
|
fclose (fp); |
|
|
return 0; |
|
126 |
} |
} |
127 |
|
|
128 |
int |
int |
346 |
} |
} |
347 |
|
|
348 |
mailbox_t |
mailbox_t |
349 |
mh_open_folder () |
mh_open_folder (const char *folder) |
350 |
{ |
{ |
351 |
mailbox_t mbox = NULL; |
mailbox_t mbox = NULL; |
352 |
|
char *name; |
353 |
if (mailbox_create_default (&mbox, current_folder)) |
|
354 |
|
name = mh_expand_name (folder, 1); |
355 |
|
if (mailbox_create_default (&mbox, name)) |
356 |
{ |
{ |
357 |
mh_error ("Can't create mailbox %s: %s", |
mh_error ("Can't create mailbox %s: %s", |
358 |
current_folder, strerror (errno)); |
name, strerror (errno)); |
359 |
exit (1); |
exit (1); |
360 |
} |
} |
361 |
|
|
362 |
if (mailbox_open (mbox, MU_STREAM_READ)) |
if (mailbox_open (mbox, MU_STREAM_READ)) |
363 |
{ |
{ |
364 |
mh_error ("Can't open mailbox %s: %s", current_folder, strerror (errno)); |
mh_error ("Can't open mailbox %s: %s", name, strerror (errno)); |
365 |
exit (1); |
exit (1); |
366 |
} |
} |
367 |
|
|
368 |
|
free (name); |
369 |
|
|
370 |
return mbox; |
return mbox; |
371 |
} |
} |
372 |
|
|
373 |
|
char * |
374 |
|
mh_get_dir () |
375 |
|
{ |
376 |
|
char *mhdir = mh_profile_value ("Path", "Mail"); |
377 |
|
if (mhdir[0] != '/') |
378 |
|
{ |
379 |
|
char *p = mu_get_homedir (); |
380 |
|
asprintf (&mhdir, "%s/%s", p, mhdir); |
381 |
|
free (p); |
382 |
|
} |
383 |
|
else |
384 |
|
mhdir = strdup (mhdir); |
385 |
|
return mhdir; |
386 |
|
} |
387 |
|
|
388 |
|
const char * |
389 |
|
mh_expand_name (const char *name, int is_folder) |
390 |
|
{ |
391 |
|
char *tmp = NULL; |
392 |
|
char *p = NULL; |
393 |
|
|
394 |
|
tmp = mu_tilde_expansion (name, "/", NULL); |
395 |
|
if (tmp[0] == '+') |
396 |
|
name = tmp + 1; |
397 |
|
else |
398 |
|
name = tmp; |
399 |
|
|
400 |
|
if (is_folder) |
401 |
|
asprintf (&p, "mh:%s/%s", mu_path_folder_dir, name); |
402 |
|
else |
403 |
|
asprintf (&p, "%s/%s", mu_path_folder_dir, name); |
404 |
|
free (tmp); |
405 |
|
return p; |
406 |
|
} |
407 |
|
|
408 |
|
int |
409 |
|
mh_iterate (mailbox_t mbox, mh_msgset_t *msgset, |
410 |
|
mh_iterator_fp itr, void *data) |
411 |
|
{ |
412 |
|
int rc; |
413 |
|
int last = 0; |
414 |
|
size_t i, total = 0; |
415 |
|
|
416 |
|
if (rc = mailbox_messages_count (mbox, &total)) |
417 |
|
{ |
418 |
|
mh_error ("can't count messages in %s: %s", |
419 |
|
current_folder, mu_errstring (rc)); |
420 |
|
exit (1); |
421 |
|
} |
422 |
|
|
423 |
|
for (i = 1; i <= total; i++) |
424 |
|
{ |
425 |
|
message_t msg; |
426 |
|
size_t num; |
427 |
|
int rc; |
428 |
|
|
429 |
|
if ((rc = mailbox_get_message (mbox, i, &msg)) != 0) |
430 |
|
{ |
431 |
|
mh_error ("can't get message %d: %s", i, mu_errstring (rc)); |
432 |
|
return 1; |
433 |
|
} |
434 |
|
|
435 |
|
if ((rc = mh_message_number (msg, &num)) != 0) |
436 |
|
{ |
437 |
|
mh_error ("can't get sequence number for message %d: %s", |
438 |
|
i, mu_errstring (rc)); |
439 |
|
return 1; |
440 |
|
} |
441 |
|
|
442 |
|
rc = mh_msgset_member (msgset, num); |
443 |
|
if (rc == last + 1) |
444 |
|
{ |
445 |
|
itr (mbox, msg, num, data); |
446 |
|
last = rc; |
447 |
|
} |
448 |
|
else if (rc && last && last < msgset->count) |
449 |
|
break; |
450 |
|
} |
451 |
|
if (last < msgset->count) |
452 |
|
{ |
453 |
|
mh_error ("message %d does not exist", msgset->list[last]); |
454 |
|
exit (1); |
455 |
|
} |
456 |
|
|
457 |
|
return 0; |
458 |
|
} |