NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
compress.c
Go to the documentation of this file.
1 
37 #include "config.h"
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include "mutt/lib.h"
45 #include "config/lib.h"
46 #include "core/lib.h"
47 #include "gui/lib.h"
48 #include "lib.h"
49 #include "format_flags.h"
50 #include "hook.h"
51 #include "mutt_commands.h"
52 #include "mutt_globals.h"
53 #include "muttlib.h"
54 #include "mx.h"
55 #include "protos.h"
56 
57 struct Email;
58 
59 static const struct Command comp_commands[] = {
60  // clang-format off
61  { "append-hook", mutt_parse_hook, MUTT_APPEND_HOOK },
62  { "close-hook", mutt_parse_hook, MUTT_CLOSE_HOOK },
63  { "open-hook", mutt_parse_hook, MUTT_OPEN_HOOK },
64  // clang-format on
65 };
66 
70 void mutt_comp_init(void)
71 {
73 }
74 
86 static bool lock_realpath(struct Mailbox *m, bool excl)
87 {
88  if (!m || !m->compress_info)
89  return false;
90 
91  struct CompressInfo *ci = m->compress_info;
92 
93  if (ci->locked)
94  return true;
95 
96  if (excl)
97  ci->fp_lock = fopen(m->realpath, "a");
98  else
99  ci->fp_lock = fopen(m->realpath, "r");
100  if (!ci->fp_lock)
101  {
102  mutt_perror(m->realpath);
103  return false;
104  }
105 
106  int r = mutt_file_lock(fileno(ci->fp_lock), excl, true);
107  if (r == 0)
108  ci->locked = true;
109  else if (excl)
110  {
112  m->readonly = true;
113  return true;
114  }
115 
116  return r == 0;
117 }
118 
125 static void unlock_realpath(struct Mailbox *m)
126 {
127  if (!m || !m->compress_info)
128  return;
129 
130  struct CompressInfo *ci = m->compress_info;
131 
132  if (!ci->locked)
133  return;
134 
135  mutt_file_unlock(fileno(ci->fp_lock));
136 
137  ci->locked = false;
139 }
140 
151 static int setup_paths(struct Mailbox *m)
152 {
153  if (!m)
154  return -1;
155 
156  /* Setup the right paths */
158 
159  /* We will uncompress to TMPDIR */
160  struct Buffer *buf = mutt_buffer_pool_get();
161  mutt_buffer_mktemp(buf);
162  mutt_buffer_copy(&m->pathbuf, buf);
164 
165  FILE *fp = mutt_file_fopen(mailbox_path(m), "w");
166  if (!fp)
167  return -1;
168 
169  mutt_file_fclose(&fp);
170  return 0;
171 }
172 
179 static void store_size(const struct Mailbox *m)
180 {
181  if (!m || !m->compress_info)
182  return;
183 
184  struct CompressInfo *ci = m->compress_info;
185 
186  ci->size = mutt_file_get_size(m->realpath);
187 }
188 
197 static struct CompressInfo *set_compress_info(struct Mailbox *m)
198 {
199  if (!m)
200  return NULL;
201 
202  if (m->compress_info)
203  return m->compress_info;
204 
205  /* Open is compulsory */
206  const char *o = mutt_find_hook(MUTT_OPEN_HOOK, mailbox_path(m));
207  if (!o)
208  return NULL;
209 
210  const char *c = mutt_find_hook(MUTT_CLOSE_HOOK, mailbox_path(m));
211  const char *a = mutt_find_hook(MUTT_APPEND_HOOK, mailbox_path(m));
212 
213  struct CompressInfo *ci = mutt_mem_calloc(1, sizeof(struct CompressInfo));
214  m->compress_info = ci;
215 
216  ci->cmd_open = mutt_str_dup(o);
217  ci->cmd_close = mutt_str_dup(c);
218  ci->cmd_append = mutt_str_dup(a);
219 
220  return ci;
221 }
222 
227 static void compress_info_free(struct Mailbox *m)
228 {
229  if (!m || !m->compress_info)
230  return;
231 
232  struct CompressInfo *ci = m->compress_info;
233  FREE(&ci->cmd_open);
234  FREE(&ci->cmd_close);
235  FREE(&ci->cmd_append);
236 
237  unlock_realpath(m);
238 
239  FREE(&m->compress_info);
240 }
241 
250 static const char *compress_format_str(char *buf, size_t buflen, size_t col, int cols,
251  char op, const char *src, const char *prec,
252  const char *if_str, const char *else_str,
253  intptr_t data, MuttFormatFlags flags)
254 {
255  if (!buf || (data == 0))
256  return src;
257 
258  struct Mailbox *m = (struct Mailbox *) data;
259 
260  /* NOTE the compressed file config vars expect %f and %t to be
261  * surrounded by '' (unlike other NeoMutt config vars, which add the
262  * outer quotes for the user). This is why we use the
263  * mutt_buffer_quote_filename() form with add_outer of false. */
264  struct Buffer *quoted = mutt_buffer_pool_get();
265  switch (op)
266  {
267  case 'f':
268  /* Compressed file */
269  mutt_buffer_quote_filename(quoted, m->realpath, false);
270  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
271  break;
272  case 't':
273  /* Plaintext, temporary file */
274  mutt_buffer_quote_filename(quoted, mailbox_path(m), false);
275  snprintf(buf, buflen, "%s", mutt_buffer_string(quoted));
276  break;
277  }
278 
279  mutt_buffer_pool_release(&quoted);
280  return src;
281 }
282 
302 static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
303 {
304  if (!m || !cmd || !buf)
305  return;
306 
307  mutt_expando_format(buf, buflen, 0, buflen, cmd, compress_format_str,
308  (intptr_t) m, MUTT_FORMAT_NO_FLAGS);
309 }
310 
322 static int execute_command(struct Mailbox *m, const char *command, const char *progress)
323 {
324  if (!m || !command || !progress)
325  return 0;
326 
327  if (m->verbose)
328  mutt_message(progress, m->realpath);
329 
330  int rc = 1;
331  char sys_cmd[STR_COMMAND];
332 
333  mutt_sig_block();
334  endwin();
335  fflush(stdout);
336 
337  expand_command_str(m, command, sys_cmd, sizeof(sys_cmd));
338 
339  if (mutt_system(sys_cmd) != 0)
340  {
341  rc = 0;
343  mutt_error(_("Error running \"%s\""), sys_cmd);
344  }
345 
347 
348  return rc;
349 }
350 
363 {
364  if (!m)
365  return false;
366 
367  /* If this succeeds, we know there's an open-hook */
368  struct CompressInfo *ci = set_compress_info(m);
369  if (!ci)
370  return false;
371 
372  /* We have an open-hook, so to append we need an append-hook,
373  * or a close-hook. */
374  if (ci->cmd_append || ci->cmd_close)
375  return true;
376 
377  mutt_error(_("Can't append without an append-hook or close-hook : %s"), mailbox_path(m));
378  return false;
379 }
380 
391 bool mutt_comp_can_read(const char *path)
392 {
393  if (!path)
394  return false;
395 
396  if (mutt_find_hook(MUTT_OPEN_HOOK, path))
397  return true;
398 
399  return false;
400 }
401 
411 int mutt_comp_valid_command(const char *cmd)
412 {
413  if (!cmd)
414  return 0;
415 
416  return strstr(cmd, "%f") && strstr(cmd, "%t");
417 }
418 
422 static bool comp_ac_owns_path(struct Account *a, const char *path)
423 {
424  return false;
425 }
426 
430 static bool comp_ac_add(struct Account *a, struct Mailbox *m)
431 {
432  return true;
433 }
434 
443 static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
444 {
445  struct CompressInfo *ci = set_compress_info(m);
446  if (!ci)
447  return MX_OPEN_ERROR;
448 
449  /* If there's no close-hook, or the file isn't writable */
450  if (!ci->cmd_close || (access(mailbox_path(m), W_OK) != 0))
451  m->readonly = true;
452 
453  if (setup_paths(m) != 0)
454  goto cmo_fail;
455  store_size(m);
456 
457  if (!lock_realpath(m, false))
458  {
459  mutt_error(_("Unable to lock mailbox"));
460  goto cmo_fail;
461  }
462 
463  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
464  if (rc == 0)
465  goto cmo_fail;
466 
467  unlock_realpath(m);
468 
470  if (m->type == MUTT_UNKNOWN)
471  {
472  mutt_error(_("Can't identify the contents of the compressed file"));
473  goto cmo_fail;
474  }
475 
476  ci->child_ops = mx_get_ops(m->type);
477  if (!ci->child_ops)
478  {
479  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
480  goto cmo_fail;
481  }
482 
483  m->account->type = m->type;
484  return ci->child_ops->mbox_open(m);
485 
486 cmo_fail:
487  /* remove the partial uncompressed file */
488  (void) remove(mailbox_path(m));
490  return MX_OPEN_ERROR;
491 }
492 
501 static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
502 {
503  /* If this succeeds, we know there's an open-hook */
504  struct CompressInfo *ci = set_compress_info(m);
505  if (!ci)
506  return false;
507 
508  /* To append we need an append-hook or a close-hook */
509  if (!ci->cmd_append && !ci->cmd_close)
510  {
511  mutt_error(_("Can't append without an append-hook or close-hook : %s"),
512  mailbox_path(m));
513  goto cmoa_fail1;
514  }
515 
516  if (setup_paths(m) != 0)
517  goto cmoa_fail2;
518 
519  /* Lock the realpath for the duration of the append.
520  * It will be unlocked in the close */
521  if (!lock_realpath(m, true))
522  {
523  mutt_error(_("Unable to lock mailbox"));
524  goto cmoa_fail2;
525  }
526 
527  /* Open the existing mailbox, unless we are appending */
528  if (!ci->cmd_append && (mutt_file_get_size(m->realpath) > 0))
529  {
530  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
531  if (rc == 0)
532  {
533  mutt_error(_("Compress command failed: %s"), ci->cmd_open);
534  goto cmoa_fail2;
535  }
537  }
538  else
539  {
540  m->type = cs_subset_enum(NeoMutt->sub, "mbox_type");
541  }
542 
543  /* We can only deal with mbox and mmdf mailboxes */
544  if ((m->type != MUTT_MBOX) && (m->type != MUTT_MMDF))
545  {
546  mutt_error(_("Unsupported mailbox type for appending"));
547  goto cmoa_fail2;
548  }
549 
550  ci->child_ops = mx_get_ops(m->type);
551  if (!ci->child_ops)
552  {
553  mutt_error(_("Can't find mailbox ops for mailbox type %d"), m->type);
554  goto cmoa_fail2;
555  }
556 
557  if (!ci->child_ops->mbox_open_append(m, flags))
558  goto cmoa_fail2;
559 
560  return true;
561 
562 cmoa_fail2:
563  /* remove the partial uncompressed file */
564  (void) remove(mailbox_path(m));
565 cmoa_fail1:
566  /* Free the compress_info to prevent close from trying to recompress */
568 
569  return false;
570 }
571 
582 static enum MxStatus comp_mbox_check(struct Mailbox *m)
583 {
584  if (!m->compress_info)
585  return MX_STATUS_ERROR;
586 
587  struct CompressInfo *ci = m->compress_info;
588 
589  const struct MxOps *ops = ci->child_ops;
590  if (!ops)
591  return MX_STATUS_ERROR;
592 
593  int size = mutt_file_get_size(m->realpath);
594  if (size == ci->size)
595  return MX_STATUS_OK;
596 
597  if (!lock_realpath(m, false))
598  {
599  mutt_error(_("Unable to lock mailbox"));
600  return MX_STATUS_ERROR;
601  }
602 
603  int rc = execute_command(m, ci->cmd_open, _("Decompressing %s"));
604  store_size(m);
605  unlock_realpath(m);
606  if (rc == 0)
607  return MX_STATUS_ERROR;
608 
609  return ops->mbox_check(m);
610 }
611 
618 static enum MxStatus comp_mbox_sync(struct Mailbox *m)
619 {
620  if (!m->compress_info)
621  return MX_STATUS_ERROR;
622 
623  struct CompressInfo *ci = m->compress_info;
624 
625  if (!ci->cmd_close)
626  {
627  mutt_error(_("Can't sync a compressed file without a close-hook"));
628  return MX_STATUS_ERROR;
629  }
630 
631  const struct MxOps *ops = ci->child_ops;
632  if (!ops)
633  return MX_STATUS_ERROR;
634 
635  if (!lock_realpath(m, true))
636  {
637  mutt_error(_("Unable to lock mailbox"));
638  return MX_STATUS_ERROR;
639  }
640 
641  enum MxStatus check = comp_mbox_check(m);
642  if (check != MX_STATUS_OK)
643  goto sync_cleanup;
644 
645  check = ops->mbox_sync(m);
646  if (check != MX_STATUS_OK)
647  goto sync_cleanup;
648 
649  int rc = execute_command(m, ci->cmd_close, _("Compressing %s"));
650  if (rc == 0)
651  {
652  check = MX_STATUS_ERROR;
653  goto sync_cleanup;
654  }
655 
656  check = MX_STATUS_OK;
657 
658 sync_cleanup:
659  store_size(m);
660  unlock_realpath(m);
661  return check;
662 }
663 
670 static enum MxStatus comp_mbox_close(struct Mailbox *m)
671 {
672  if (!m->compress_info)
673  return MX_STATUS_ERROR;
674 
675  struct CompressInfo *ci = m->compress_info;
676 
677  const struct MxOps *ops = ci->child_ops;
678  if (!ops)
679  {
681  return MX_STATUS_ERROR;
682  }
683 
684  ops->mbox_close(m);
685 
686  /* sync has already been called, so we only need to delete some files */
687  if (m->append)
688  {
689  const char *append = NULL;
690  const char *msg = NULL;
691 
692  /* The file exists and we can append */
693  if ((access(m->realpath, F_OK) == 0) && ci->cmd_append)
694  {
695  append = ci->cmd_append;
696  msg = _("Compressed-appending to %s...");
697  }
698  else
699  {
700  append = ci->cmd_close;
701  msg = _("Compressing %s");
702  }
703 
704  int rc = execute_command(m, append, msg);
705  if (rc == 0)
706  {
708  mutt_error(_("Error. Preserving temporary file: %s"), mailbox_path(m));
709  }
710  else
711  remove(mailbox_path(m));
712 
713  unlock_realpath(m);
714  }
715  else
716  {
717  /* If the file was removed, remove the compressed folder too */
718  if (access(mailbox_path(m), F_OK) != 0)
719  {
720  const bool c_save_empty = cs_subset_bool(NeoMutt->sub, "save_empty");
721  if (!c_save_empty)
722  {
723  remove(m->realpath);
724  }
725  }
726  else
727  {
728  remove(mailbox_path(m));
729  }
730  }
731 
733 
734  return MX_STATUS_OK;
735 }
736 
740 static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
741 {
742  if (!m->compress_info)
743  return false;
744 
745  struct CompressInfo *ci = m->compress_info;
746 
747  const struct MxOps *ops = ci->child_ops;
748  if (!ops)
749  return false;
750 
751  /* Delegate */
752  return ops->msg_open(m, msg, msgno);
753 }
754 
758 static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
759 {
760  if (!m->compress_info)
761  return false;
762 
763  struct CompressInfo *ci = m->compress_info;
764 
765  const struct MxOps *ops = ci->child_ops;
766  if (!ops)
767  return false;
768 
769  /* Delegate */
770  return ops->msg_open_new(m, msg, e);
771 }
772 
776 static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
777 {
778  if (!m->compress_info)
779  return -1;
780 
781  struct CompressInfo *ci = m->compress_info;
782 
783  const struct MxOps *ops = ci->child_ops;
784  if (!ops)
785  return -1;
786 
787  /* Delegate */
788  return ops->msg_commit(m, msg);
789 }
790 
794 static int comp_msg_close(struct Mailbox *m, struct Message *msg)
795 {
796  if (!m->compress_info)
797  return -1;
798 
799  struct CompressInfo *ci = m->compress_info;
800 
801  const struct MxOps *ops = ci->child_ops;
802  if (!ops)
803  return -1;
804 
805  /* Delegate */
806  return ops->msg_close(m, msg);
807 }
808 
812 static int comp_msg_padding_size(struct Mailbox *m)
813 {
814  if (!m->compress_info)
815  return 0;
816 
817  struct CompressInfo *ci = m->compress_info;
818 
819  const struct MxOps *ops = ci->child_ops;
820  if (!ops || !ops->msg_padding_size)
821  return 0;
822 
823  return ops->msg_padding_size(m);
824 }
825 
829 static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
830 {
831  if (!m->compress_info)
832  return 0;
833 
834  struct CompressInfo *ci = m->compress_info;
835 
836  const struct MxOps *ops = ci->child_ops;
837  if (!ops || !ops->msg_save_hcache)
838  return 0;
839 
840  return ops->msg_save_hcache(m, e);
841 }
842 
846 static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
847 {
848  if (!m->compress_info)
849  return 0;
850 
851  struct CompressInfo *ci = m->compress_info;
852 
853  const struct MxOps *ops = ci->child_ops;
854  if (!ops || !ops->tags_edit)
855  return 0;
856 
857  return ops->tags_edit(m, tags, buf);
858 }
859 
863 static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
864 {
865  if (!m->compress_info)
866  return 0;
867 
868  struct CompressInfo *ci = m->compress_info;
869 
870  const struct MxOps *ops = ci->child_ops;
871  if (!ops || !ops->tags_commit)
872  return 0;
873 
874  return ops->tags_commit(m, e, buf);
875 }
876 
880 static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
881 {
882  if (!st || !S_ISREG(st->st_mode))
883  return MUTT_UNKNOWN;
884 
885  if (mutt_comp_can_read(path))
886  return MUTT_COMPRESSED;
887 
888  return MUTT_UNKNOWN;
889 }
890 
894 static int comp_path_canon(char *buf, size_t buflen)
895 {
896  mutt_path_canon(buf, buflen, HomeDir, false);
897  return 0;
898 }
899 
903 static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
904 {
905  if (mutt_path_abbr_folder(buf, folder))
906  return 0;
907 
908  if (mutt_path_pretty(buf, buflen, HomeDir, false))
909  return 0;
910 
911  return -1;
912 }
913 
917 static int comp_path_parent(char *buf, size_t buflen)
918 {
919  if (mutt_path_parent(buf))
920  return 0;
921 
922  if (buf[0] == '~')
923  mutt_path_canon(buf, buflen, HomeDir, false);
924 
925  if (mutt_path_parent(buf))
926  return 0;
927 
928  return -1;
929 }
930 
937 struct MxOps MxCompOps = {
938  // clang-format off
940  .name = "compressed",
941  .is_local = true,
942  .ac_owns_path = comp_ac_owns_path,
943  .ac_add = comp_ac_add,
944  .mbox_open = comp_mbox_open,
945  .mbox_open_append = comp_mbox_open_append,
946  .mbox_check = comp_mbox_check,
947  .mbox_check_stats = NULL,
948  .mbox_sync = comp_mbox_sync,
949  .mbox_close = comp_mbox_close,
950  .msg_open = comp_msg_open,
951  .msg_open_new = comp_msg_open_new,
952  .msg_commit = comp_msg_commit,
953  .msg_close = comp_msg_close,
954  .msg_padding_size = comp_msg_padding_size,
955  .msg_save_hcache = comp_msg_save_hcache,
956  .tags_edit = comp_tags_edit,
957  .tags_commit = comp_tags_commit,
958  .path_probe = comp_path_probe,
959  .path_canon = comp_path_canon,
960  .path_pretty = comp_path_pretty,
961  .path_parent = comp_path_parent,
962  .path_is_empty = NULL,
963  // clang-format on
964 };
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
static const struct Command comp_commands[]
Definition: compress.c:59
static void compress_info_free(struct Mailbox *m)
Frees the compress info members and structure.
Definition: compress.c:227
static int setup_paths(struct Mailbox *m)
Set the mailbox paths.
Definition: compress.c:151
static int execute_command(struct Mailbox *m, const char *command, const char *progress)
Run a system command.
Definition: compress.c:322
void mutt_comp_init(void)
Setup feature commands.
Definition: compress.c:70
static void store_size(const struct Mailbox *m)
Save the size of the compressed file.
Definition: compress.c:179
static bool lock_realpath(struct Mailbox *m, bool excl)
Try to lock the Mailbox.realpath.
Definition: compress.c:86
static struct CompressInfo * set_compress_info(struct Mailbox *m)
Find the compress hooks for a mailbox.
Definition: compress.c:197
bool mutt_comp_can_append(struct Mailbox *m)
Can we append to this path?
Definition: compress.c:362
static void unlock_realpath(struct Mailbox *m)
Unlock the mailbox->realpath.
Definition: compress.c:125
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:411
static void expand_command_str(const struct Mailbox *m, const char *cmd, char *buf, int buflen)
Expand placeholders in command string.
Definition: compress.c:302
bool mutt_comp_can_read(const char *path)
Can we read from this file?
Definition: compress.c:391
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Definition: mutt_globals.h:49
Convenience wrapper for the core headers.
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1231
void mutt_buffer_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:891
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1279
long mutt_file_get_size(const char *path)
Get the size of a file.
Definition: file.c:1551
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
Flags to control mutt_expando_format()
#define MUTT_FORMAT_NO_FLAGS
No flags are set.
Definition: format_flags.h:30
uint8_t MuttFormatFlags
Flags for mutt_expando_format(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: format_flags.h:29
enum CommandResult mutt_parse_hook(struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
Parse the 'hook' family of commands - Implements Command::parse() -.
Definition: hook.c:126
static const char * compress_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Expand the filenames in a command string - Implements format_t -.
Definition: compress.c:250
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
Definition: muttlib.c:777
#define mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
static bool comp_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Implements MxOps::ac_add() -.
Definition: compress.c:430
static bool comp_ac_owns_path(struct Account *a, const char *path)
Check whether an Account owns a Mailbox path - Implements MxOps::ac_owns_path() -.
Definition: compress.c:422
struct MxOps MxCompOps
Compressed Mailbox - Implements MxOps -.
Definition: compress.c:937
static enum MxStatus comp_mbox_check(struct Mailbox *m)
Check for new mail - Implements MxOps::mbox_check() -.
Definition: compress.c:582
static enum MxStatus comp_mbox_close(struct Mailbox *m)
Close a Mailbox - Implements MxOps::mbox_close() -.
Definition: compress.c:670
static bool comp_mbox_open_append(struct Mailbox *m, OpenMailboxFlags flags)
Open a Mailbox for appending - Implements MxOps::mbox_open_append() -.
Definition: compress.c:501
static enum MxOpenReturns comp_mbox_open(struct Mailbox *m)
Open a Mailbox - Implements MxOps::mbox_open() -.
Definition: compress.c:443
static enum MxStatus comp_mbox_sync(struct Mailbox *m)
Save changes to the Mailbox - Implements MxOps::mbox_sync() -.
Definition: compress.c:618
static int comp_msg_close(struct Mailbox *m, struct Message *msg)
Close an email - Implements MxOps::msg_close() -.
Definition: compress.c:794
static int comp_msg_commit(struct Mailbox *m, struct Message *msg)
Save changes to an email - Implements MxOps::msg_commit() -.
Definition: compress.c:776
static bool comp_msg_open_new(struct Mailbox *m, struct Message *msg, const struct Email *e)
Open a new message in a Mailbox - Implements MxOps::msg_open_new() -.
Definition: compress.c:758
static bool comp_msg_open(struct Mailbox *m, struct Message *msg, int msgno)
Open an email message in a Mailbox - Implements MxOps::msg_open() -.
Definition: compress.c:740
static int comp_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Implements MxOps::msg_padding_size() -.
Definition: compress.c:812
static int comp_msg_save_hcache(struct Mailbox *m, struct Email *e)
Save message to the header cache - Implements MxOps::msg_save_hcache() -.
Definition: compress.c:829
static int comp_path_canon(char *buf, size_t buflen)
Canonicalise a Mailbox path - Implements MxOps::path_canon() -.
Definition: compress.c:894
static int comp_path_parent(char *buf, size_t buflen)
Find the parent of a Mailbox path - Implements MxOps::path_parent() -.
Definition: compress.c:917
static int comp_path_pretty(char *buf, size_t buflen, const char *folder)
Abbreviate a Mailbox path - Implements MxOps::path_pretty() -.
Definition: compress.c:903
static enum MailboxType comp_path_probe(const char *path, const struct stat *st)
Is this a compressed Mailbox? - Implements MxOps::path_probe() -.
Definition: compress.c:880
static int comp_tags_commit(struct Mailbox *m, struct Email *e, const char *buf)
Save the tags to a message - Implements MxOps::tags_commit() -.
Definition: compress.c:863
static int comp_tags_edit(struct Mailbox *m, const char *tags, struct Buffer *buf)
Prompt and validate new messages tags - Implements MxOps::tags_edit() -.
Definition: compress.c:846
Convenience wrapper for the gui headers.
char * mutt_find_hook(HookFlags type, const char *pat)
Find a matching hook.
Definition: hook.c:631
Parse and execute user-defined hooks.
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:51
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:53
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:52
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:211
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
@ MUTT_COMPRESSED
Compressed file Mailbox type.
Definition: mailbox.h:53
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition: mailbox.h:44
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
Convenience wrapper for the library headers.
#define _(a)
Definition: message.h:28
bool mutt_path_abbr_folder(char *buf, const char *folder)
Create a folder abbreviation.
Definition: path.c:490
bool mutt_path_pretty(char *buf, size_t buflen, const char *homedir, bool is_dir)
Tidy a filesystem path.
Definition: path.c:186
bool mutt_path_canon(char *buf, size_t buflen, const char *homedir, bool is_dir)
Create the canonical version of a path.
Definition: path.c:285
bool mutt_path_parent(char *buf)
Find the parent of a path.
Definition: path.c:458
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
Definitions of NeoMutt commands.
#define COMMANDS_REGISTER(cmds)
Definition: mutt_commands.h:47
Hundreds of global variables to back the user variables.
Some miscellaneous functions.
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
const struct MxOps * mx_get_ops(enum MailboxType type)
Get mailbox operations.
Definition: mx.c:141
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
Definition: mx.c:1327
API for mailboxes.
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:60
MxOpenReturns
Return values for mbox_open()
Definition: mxapi.h:97
@ MX_OPEN_ERROR
Open failed with an error.
Definition: mxapi.h:99
MxStatus
Return values from mbox_check(), mbox_check_stats(), mbox_snc(), and mbox_close()
Definition: mxapi.h:84
@ MX_STATUS_ERROR
An error occurred.
Definition: mxapi.h:85
@ MX_STATUS_OK
No changes.
Definition: mxapi.h:86
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
Prototypes for many functions.
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
Key value store.
#define STR_COMMAND
Enough space for a long command line.
Definition: string2.h:35
A group of associated Mailboxes.
Definition: account.h:37
enum MailboxType type
Type of Mailboxes this Account contains.
Definition: account.h:38
String manipulation buffer.
Definition: buffer.h:34
Private data for compress.
Definition: lib.h:47
const char * cmd_append
append-hook command
Definition: lib.h:48
FILE * fp_lock
fp used for locking
Definition: lib.h:54
const char * cmd_open
open-hook command
Definition: lib.h:50
const struct MxOps * child_ops
callbacks of de-compressed file
Definition: lib.h:52
bool locked
if realpath is locked
Definition: lib.h:53
const char * cmd_close
close-hook command
Definition: lib.h:49
long size
size of the compressed file
Definition: lib.h:51
The envelope/body of an email.
Definition: email.h:37
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:110
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
struct Buffer pathbuf
Path of the Mailbox.
Definition: mailbox.h:80
struct Account * account
Account that owns this Mailbox.
Definition: mailbox.h:128
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
bool readonly
Don't allow changes to the mailbox.
Definition: mailbox.h:116
bool verbose
Display status messages?
Definition: mailbox.h:115
A local copy of an email.
Definition: mxapi.h:43
Definition: mxapi.h:112
int(* tags_commit)(struct Mailbox *m, struct Email *e, const char *buf)
Definition: mxapi.h:360
int(* msg_save_hcache)(struct Mailbox *m, struct Email *e)
Definition: mxapi.h:324
enum MailboxType type
Mailbox type, e.g. MUTT_IMAP.
Definition: mxapi.h:113
int(* msg_padding_size)(struct Mailbox *m)
Definition: mxapi.h:308
int(* tags_edit)(struct Mailbox *m, const char *tags, struct Buffer *buf)
Definition: mxapi.h:342
int(* msg_commit)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:279
enum MxOpenReturns(* mbox_open)(struct Mailbox *m)
Definition: mxapi.h:160
int(* msg_close)(struct Mailbox *m, struct Message *msg)
Definition: mxapi.h:295
bool(* msg_open_new)(struct Mailbox *m, struct Message *msg, const struct Email *e)
Definition: mxapi.h:263
enum MxStatus(* mbox_close)(struct Mailbox *m)
Definition: mxapi.h:228
enum MxStatus(* mbox_sync)(struct Mailbox *m)
Definition: mxapi.h:215
bool(* mbox_open_append)(struct Mailbox *m, OpenMailboxFlags flags)
Definition: mxapi.h:175
enum MxStatus(* mbox_check)(struct Mailbox *m)
Definition: mxapi.h:188
bool(* msg_open)(struct Mailbox *m, struct Message *msg, int msgno)
Definition: mxapi.h:246
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39