#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <signal.h>
static struct dotlock_settings dotlock_settings = {
};
static struct ioloop *ioloop;
+static bool success = FALSE;
-static void sig_die(int signo ATTR_UNUSED, void *context ATTR_UNUSED)
+static void sig_die(int signo, void *context ATTR_UNUSED)
{
+ success = signo == SIGTERM;
io_loop_stop(ioloop);
}
dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL;
dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL;
+ path = t_strconcat(path, "/" MAILDIR_UIDLIST_NAME, NULL);
return file_dotlock_create(&dotlock_settings, path, 0, dotlock_r);
}
{
struct dotlock *dotlock;
unsigned int timeout;
-
- lib_init();
- ioloop = io_loop_create();
+ pid_t pid, parent_pid;
if (argc != 3) {
- printf("Usage: maildirlock <path> <timeout>\n"
- " - SIGTERM will release the lock.\n");
+ fprintf(stderr, "Usage: maildirlock <path> <timeout>\n"
+ " - SIGTERM will release the lock.\n");
return 1;
}
+ parent_pid = getpid();
- timeout = strtoul(argv[2], NULL, 10);
- if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
+ pid = fork();
+ if (pid == (pid_t)-1) {
+ fprintf(stderr, "fork() failed: %m");
return 1;
+ }
+ /* call lib_init() only after fork so that PID gets set correctly */
+ lib_init();
+ ioloop = io_loop_create();
lib_signals_init();
lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
+ lib_signals_set_handler(SIGCHLD, TRUE, sig_die, NULL);
+
+ if (pid != 0) {
+ /* master - wait for the child process to finish locking */
+ io_loop_run(ioloop);
+ if (!success)
+ return 1;
+ printf("%s", dec2str(pid));
+ return 0;
+ }
+
+ /* child process - stdout has to be closed so that caller knows when
+ to stop reading it. */
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+
+ timeout = strtoul(argv[2], NULL, 10);
+ if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
+ return 1;
+
+ /* locked - send a */
+ if (kill(parent_pid, SIGTERM) < 0)
+ i_fatal("kill(parent, SIGTERM) failed: %m");
io_loop_run(ioloop);
file_dotlock_delete(&dotlock);