aboutsummaryrefslogtreecommitdiffstats
path: root/lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'lock.c')
-rw-r--r--lock.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/lock.c b/lock.c
index e69de29b..5780c056 100644
--- a/lock.c
+++ b/lock.c
@@ -0,0 +1,130 @@
+/*
+ * lock.c -- cross-platform concurrency locking for fetchmail
+ *
+ * For license terms, see the file COPYING in this directory.
+ */
+#include "config.h"
+
+#include <stdio.h>
+#if defined(STDC_HEADERS)
+#include <stdlib.h>
+#endif
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+#include "fetchmail.h"
+#include "i18n.h"
+
+static char *lockfile; /* name of lockfile */
+static int lock_acquired; /* have we acquired a lock */
+
+void lock_setup(void)
+/* set up the global lockfile name */
+{
+ /* set up to do lock protocol */
+#define FETCHMAIL_PIDFILE "fetchmail.pid"
+ if (!getuid()) {
+ xalloca(lockfile, char *,
+ sizeof(PID_DIR) + sizeof(FETCHMAIL_PIDFILE));
+ sprintf(lockfile, "%s/%s", PID_DIR, FETCHMAIL_PIDFILE);
+ } else {
+ xalloca(lockfile, char *, strlen(fmhome) + sizeof(FETCHMAIL_PIDFILE) + 2);
+ strcpy(lockfile, fmhome);
+ strcat(lockfile, "/");
+ if (fmhome == home)
+ strcat(lockfile, ".");
+ strcat(lockfile, FETCHMAIL_PIDFILE);
+ }
+#undef FETCHMAIL_PIDFILE
+}
+
+#ifdef HAVE_ON_EXIT
+static void unlockit(int n, void *p)
+#else
+static void unlockit(void)
+#endif
+/* must-do actions for exit (but we can't count on being able to do malloc) */
+{
+ if (lockfile && lock_acquired)
+ unlink(lockfile);
+}
+
+void lock_dispose(void)
+/* arrange for a lock to be removed on process exit */
+{
+#ifdef HAVE_ATEXIT
+ atexit(unlockit);
+#endif
+#ifdef HAVE_ON_EXIT
+ on_exit(unlockit, (char *)NULL);
+#endif
+}
+
+int lock_state(void)
+{
+ int pid, st;
+ FILE *lockfp;
+ int bkgd = FALSE;
+
+ pid = 0;
+ if ((lockfp = fopen(lockfile, "r")) != NULL )
+ {
+ bkgd = (fscanf(lockfp, "%d %d", &pid, &st) == 2);
+
+ if (kill(pid, 0) == -1) {
+ fprintf(stderr,_("fetchmail: removing stale lockfile\n"));
+ pid = 0;
+ unlink(lockfile);
+ }
+ fclose(lockfp); /* not checking should be safe, file mode was "r" */
+ }
+
+ return(bkgd ? -pid : pid);
+}
+
+void lock_assert(void)
+/* assert that we already posess a lock */
+{
+ lock_acquired = TRUE;
+}
+
+void lock_or_die(void)
+/* get a lock on a given host or exit */
+{
+ int fd;
+ char tmpbuf[20];
+
+#ifndef O_SYNC
+#define O_SYNC 0 /* use it if we have it */
+#endif
+ if (!lock_acquired)
+ {
+ if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_SYNC, 0666)) != -1)
+ {
+ sprintf(tmpbuf,"%d", getpid());
+ write(fd, tmpbuf, strlen(tmpbuf));
+ if (run.poll_interval)
+ {
+ sprintf(tmpbuf," %d", run.poll_interval);
+ write(fd, tmpbuf, strlen(tmpbuf));
+ }
+ close(fd); /* should be safe, fd was opened with O_SYNC */
+ lock_acquired = TRUE;
+ }
+ else
+ {
+ fprintf(stderr, _("fetchmail: lock creation failed.\n"));
+ exit(PS_EXCLUDE);
+ }
+ }
+}
+
+void lock_release(void)
+/* release a lock on a given host */
+{
+ unlink(lockfile);
+}
+
+/* lock.c ends here */