NeoMutt  2025-12-11-1039-g550ac6
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
monitor.h File Reference

Monitor files for changes. More...

#include <stdbool.h>
Include dependency graph for monitor.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int mutt_monitor_add (struct Mailbox *m)
 Add a watch for a mailbox.
int mutt_monitor_remove (struct Mailbox *m)
 Remove a watch for a mailbox.
int mutt_monitor_poll (void)
 Check for filesystem changes.

Variables

bool MonitorFilesChanged
 true after a monitored file has changed
bool MonitorCurMboxChanged
 true after the current mailbox has changed

Detailed Description

Monitor files for changes.

Authors
  • Gero Treuner
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file monitor.h.

Function Documentation

◆ mutt_monitor_add()

int mutt_monitor_add ( struct Mailbox * m)

Add a watch for a mailbox.

Parameters
mMailbox to watch
Return values
0success: new or already existing monitor
-1failed: no mailbox, inaccessible file, create monitor/watcher failed

If m is NULL, try to get the current mailbox from the Index.

Definition at line 484 of file monitor.c.

485{
486 struct MonitorInfo info = { 0 };
487
488 int rc = 0;
489 enum ResolveResult desc = monitor_resolve(&info, m);
490 if (desc != RESOLVE_RES_OK_NOTEXISTING)
491 {
492 if (!m && (desc == RESOLVE_RES_OK_EXISTING))
494 rc = (desc == RESOLVE_RES_OK_EXISTING) ? 0 : -1;
495 goto cleanup;
496 }
497
498 uint32_t mask = info.is_dir ? INOTIFY_MASK_DIR : INOTIFY_MASK_FILE;
499 if (((INotifyFd == -1) && (monitor_init() == -1)) ||
500 ((desc = inotify_add_watch(INotifyFd, info.path, mask)) == -1))
501 {
502 mutt_debug(LL_DEBUG2, "inotify_add_watch failed for '%s', errno=%d %s\n",
503 info.path, errno, strerror(errno));
504 rc = -1;
505 goto cleanup;
506 }
507
508 mutt_debug(LL_DEBUG3, "inotify_add_watch descriptor=%d for '%s'\n", desc, info.path);
509 if (!m)
511
512 monitor_new(&info, desc);
513
514cleanup:
515 monitor_info_free(&info);
516 return rc;
517}
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG3
Log at debug level 3.
Definition logging2.h:47
@ LL_DEBUG2
Log at debug level 2.
Definition logging2.h:46
#define INOTIFY_MASK_DIR
Definition monitor.c:70
static int INotifyFd
Inotify file descriptor.
Definition monitor.c:58
static int MonitorCurMboxDescriptor
Monitor file descriptor of the current mailbox.
Definition monitor.c:68
static enum ResolveResult monitor_resolve(struct MonitorInfo *info, struct Mailbox *m)
Get the monitor for a mailbox.
Definition monitor.c:332
static struct Monitor * monitor_new(struct MonitorInfo *info, int descriptor)
Create a new file monitor.
Definition monitor.c:217
ResolveResult
Results for the Monitor functions.
Definition monitor.c:79
@ RESOLVE_RES_OK_NOTEXISTING
File exists, no monitor is attached.
Definition monitor.c:83
@ RESOLVE_RES_OK_EXISTING
File exists, monitor is already attached.
Definition monitor.c:84
static int monitor_init(void)
Set up file monitoring.
Definition monitor.c:168
#define INOTIFY_MASK_FILE
Definition monitor.c:71
static void monitor_info_free(struct MonitorInfo *info)
Shutdown a file monitor.
Definition monitor.c:237
Information about a monitored file.
Definition monitor.c:104
struct Monitor * monitor
Monitor for this file.
Definition monitor.c:110
bool is_dir
Is this a directory?
Definition monitor.c:106
const char * path
Filesystem path.
Definition monitor.c:107
int desc
File descriptor.
Definition monitor.c:97
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_monitor_remove()

int mutt_monitor_remove ( struct Mailbox * m)

Remove a watch for a mailbox.

Parameters
mMailbox
Return values
0monitor removed (not shared)
1monitor not removed (shared)
2no monitor

If m is NULL, try to get the current mailbox from the Index.

Definition at line 528 of file monitor.c.

529{
530 struct MonitorInfo info = { 0 };
531 struct MonitorInfo info2 = { 0 };
532 int rc = 0;
533
534 if (!m)
535 {
537 MonitorCurMboxChanged = false;
538 }
539
541 {
542 rc = 2;
543 goto cleanup;
544 }
545
546 struct Mailbox *m_cur = get_current_mailbox();
547 if (m_cur)
548 {
549 if (m)
550 {
551 if ((monitor_resolve(&info2, NULL) == RESOLVE_RES_OK_EXISTING) &&
552 (info.st_ino == info2.st_ino) && (info.st_dev == info2.st_dev))
553 {
554 rc = 1;
555 goto cleanup;
556 }
557 }
558 else
559 {
560 if (mailbox_find(m_cur->realpath))
561 {
562 rc = 1;
563 goto cleanup;
564 }
565 }
566 }
567
568 inotify_rm_watch(info.monitor->desc, INotifyFd);
569 mutt_debug(LL_DEBUG3, "inotify_rm_watch for '%s' descriptor=%d\n", info.path,
570 info.monitor->desc);
571
574
575cleanup:
576 monitor_info_free(&info);
577 monitor_info_free(&info2);
578 return rc;
579}
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:151
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition index.c:725
static void monitor_delete(struct Monitor *monitor)
Free a file monitor.
Definition monitor.c:246
bool MonitorCurMboxChanged
Set to true when the current mailbox has changed.
Definition monitor.c:55
static void monitor_check_cleanup(void)
Close down file monitoring.
Definition monitor.c:200
A mailbox.
Definition mailbox.h:81
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:83
dev_t st_dev
Device number.
Definition monitor.c:108
ino_t st_ino
Inode number.
Definition monitor.c:109
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mutt_monitor_poll()

int mutt_monitor_poll ( void )

Check for filesystem changes.

Return values
-3unknown/unexpected events: poll timeout / fds not handled by us
-2monitor detected changes, no STDIN input
-1error (see errno)
0(1) input ready from STDIN, or (2) monitoring inactive -> no poll()

Wait for I/O ready file descriptors or signals.

MonitorFilesChanged also reflects changes to monitored files.

Only STDIN and INotify file handles currently expected/supported. More would ask for common infrastructure (sockets?).

Definition at line 401 of file monitor.c.

402{
403 int rc = 0;
404 char buf[EVENT_BUFLEN]
405 __attribute__((aligned(__alignof__(struct inotify_event)))) = { 0 };
406
407 MonitorFilesChanged = false;
408
409 if (INotifyFd != -1)
410 {
411 int fds = poll(PollFds, PollFdsCount, 1000); // 1 Second
412
413 if (fds == -1)
414 {
415 rc = -1;
416 if (errno != EINTR)
417 {
418 mutt_debug(LL_DEBUG2, "poll() failed, errno=%d %s\n", errno, strerror(errno));
419 }
420 }
421 else
422 {
423 bool input_ready = false;
424 for (int i = 0; fds && (i < PollFdsCount); i++)
425 {
426 if (PollFds[i].revents)
427 {
428 fds--;
429 if (PollFds[i].fd == 0)
430 {
431 input_ready = true;
432 }
433 else if (PollFds[i].fd == INotifyFd)
434 {
435 MonitorFilesChanged = true;
436 mutt_debug(LL_DEBUG3, "file change(s) detected\n");
437 char *ptr = buf;
438 const struct inotify_event *event = NULL;
439
440 while (true)
441 {
442 int len = read(INotifyFd, buf, sizeof(buf));
443 if (len == -1)
444 {
445 if (errno != EAGAIN)
446 {
447 mutt_debug(LL_DEBUG2, "read inotify events failed, errno=%d %s\n",
448 errno, strerror(errno));
449 }
450 break;
451 }
452
453 while (ptr < (buf + len))
454 {
455 event = (const struct inotify_event *) ptr;
456 mutt_debug(LL_DEBUG3, "+ detail: descriptor=%d mask=0x%x\n",
457 event->wd, event->mask);
458 if (event->mask & IN_IGNORED)
459 monitor_handle_ignore(event->wd);
460 else if (event->wd == MonitorCurMboxDescriptor)
462 ptr += sizeof(struct inotify_event) + event->len;
463 }
464 }
465 }
466 }
467 }
468 if (!input_ready)
469 rc = MonitorFilesChanged ? -2 : -3;
470 }
471 }
472
473 return rc;
474}
static int monitor_handle_ignore(int desc)
Listen for when a backup file is closed.
Definition monitor.c:274
static size_t PollFdsCount
Number of used entries in the PollFds array.
Definition monitor.c:62
bool MonitorFilesChanged
Set to true when a monitored file has changed.
Definition monitor.c:53
#define EVENT_BUFLEN
Definition monitor.c:73
static struct pollfd * PollFds
Array of monitored file descriptors.
Definition monitor.c:66
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ MonitorFilesChanged

bool MonitorFilesChanged
extern

true after a monitored file has changed

Set to true when a monitored file has changed.

true after a monitored file has changed

Definition at line 53 of file monitor.c.

◆ MonitorCurMboxChanged

bool MonitorCurMboxChanged
extern

true after the current mailbox has changed

Set to true when the current mailbox has changed.

true after the current mailbox has changed

Definition at line 55 of file monitor.c.